js 下载和重命名文件
最编程
2024-07-17 14:11:33
...
背景
当我们将图片,视频,音乐,PDF或者其他文件上传给后端时,后端为了文件名不重复,可能会做一些处理。比如使用日期+时间戳+随机数的方式名命,又或者使用UUID或其他方式生成文件名。这就会导致一个问题。用户下载文件后,不能直观的通过文件名判断文件内容。举个例子:
- 夜曲 - 周杰伦.mp3 => 6fe3c93a-d3cd-47c6-ac54-11a6978a08cf.mp3
- xxx简历.pdf => a4e50bfc-63b0-4a19-b0c9-363c7467b2b4.pdf
- 全家福.jpg => ad58b4d1-022c-4095-aa21-829cda8f9f33.jpg 上述列子还可以通过后缀名区分,但如果你下载的文件都是同一类型的,那...
下载文件并重命名
对于浏览器来说,当你点击的链接是跳转到一张图片,一个视频,一首音乐的时候,浏览器会直接在新标签页打开并预览,如果你想下载这些文件,你需要右键另存为,或者找到下载按钮。对于压缩包,或其他无法预览的文件,则会直接下载。那有没有办法跳过右键另存为,或找下载按钮这些步骤,直接下载呢?大家应该都试过给a标签添加download属性这种方式吧。
<a href="path/ad58b4d1-022c-4095-aa21-829cda8f9f33.jpg" download="全家福">download</a>
很遗憾,大多数情况下并没有任何效果。那到底该如何实现呢?其实很简单,需要涉及到XMLHttpRequest,URL.createObjectURL()。
实现
纸上得来终觉浅,绝知此事要躬行。
话不多说,直接上代码:
<button id="btn" type="button">下载</button>
const btn = document.getElementById('btn');
btn.addEventListener('click', function () {
downloadFile('path/ad58b4d1-022c-4095-aa21-829cda8f9f33.jpg', '全家福');
});
/**
* 下载文件
* @param {string} url
* @param {string} fileName
*/
function downloadFile(url, fileName) {
const xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
// 响应类型设置为blob
xhr.responseType = 'blob';
// 请求成功
xhr.addEventListener('load', function () {
if (xhr.status === 200) {
const a = document.createElement('a');
a.href = window.URL.createObjectURL(xhr.response);
a.download = fileName;
// 将a标签添加到body中是为了更好的兼容性,谷歌浏览器可以不用添加
document.body.appendChild(a);
a.click();
// 移除
a.remove();
// 释放url
window.URL.revokeObjectURL(a.href);
}
});
// 监听下载进度
xhr.addEventListener('progress', function (e) {
let percent = Math.trunc(e.loaded / e.total * 100);
});
// 错误处理
xhr.addEventListener('error', function (e) {
// todo
});
// 发送请求
xhr.send();
}
效果图
此外,如果你想将一串字符保存为txt类型的文件,你同样可以使用Blob实现,只需要将Blob构造函数第二个参数的type属性设置为text/plain。适用于保存签名,公钥,私钥等。
/**
* 保存文件
* @param {string} str
* @param {string} fileName
*/
function saveAsFile(str, fileName) {
const blob = new Blob([str], { type: 'text/plain' });
const a = document.createElement('a');
a.href = window.URL.createObjectURL(blob);
a.download = fileName;
// 将a标签添加到body中是为了更好的兼容性,谷歌浏览器可以不用添加
document.body.appendChild(a);
a.click();
// 移除
a.remove();
// 释放url
window.URL.revokeObjectURL(a.href);
}
在线Demo:jsdemo.codeman.top/html/downlo…
存在的问题
当然此方法并不是完美的,存在以下问题。
- 非同源存在跨域问题(Demo已设置允许资源跨域)
- 会预先加载文件,如果文件比较大,网速较慢,服务器带宽比较低时,等待时间会比较长(所以Demo弄了个进度条)
推荐阅读
-
node.js 下载和安装以及环境配置超级详细教程 [Windows 版本]。
-
主机文件和 Mac 版 switchhosts 下载
-
如何保护Node.js代码:加密、混淆、编译和转为可执行文件
-
使用Nginx将.js和.css文件转换为纯文本类型
-
用Java从网络下载图片和视频到本地,然后上传到你的个人文件服务器!
-
如何在阿里云Open API中利用AK/SK(访问密钥和安全密钥)从后端下载文件?
-
修正Vite和React项目中.js文件使用JSX语法报错的解决方案
-
实战攻略:工作流引擎深度解析 - 思维导图与具体案例" 目录概览: 1. 业务场景实战合集 2. 背景介绍:处理复杂场景 - 如请假、离职流程中的多步骤审批差异 - 详细示例:请假与离职流程的应用演示 3. 案例应用实例: - 内部企业系统(如OA)中的请假、离职流程审批 - 在内容创作工具(如PPT、海报模板)提供下载功能时,针对不同租户设置个性化审批流程 4. 技术选型与实践探讨 注:图片文件名 - "思维导图.png" 和 "请假流程.png" 无需修改。
-
在Vue和Node.js项目中实现用户头像图片文件的上传功能
-
如何用HTML和JS轻松搞定图片的上传与下载操作