当后端返回的资源是链接时,此时可以使用 a 标签或者 window.location.href直接打开。
在H5中,a标签新增了download 属性,包含该属性的链接被点击时,浏览器会以下载文件方式下载 href 属性上的链接。
<a href="https://example.com" download="example.html">下载</a>
// 或者封装
function download(href, title) {
const a = document.createElement('a');
a.setAttribute('href', href);
a.setAttribute('download', title);
a.click();
}
download('https://example.com', 'test')
window.location.href === 'https://example.com'
当后端返回的文件是流文件时,以 umi-request 请求方法为例
首先应在请求中设置返回类型:responseType: "blob"
import request from "umi-request";
export const downLoad = (url, fileName) =>
request(url, {
method: "POST",
data: data,
responseType: "blob", // 代表内存之中的一段为二进制
}).then(data) => {
const blob = data;
let link = document.createElement("a");
link.href = URL.createObjectURL( new Blob([blob], { type: "application/vnd.ms-excel" }) );
link.download = fileName;
document.body.appendChild(link);
link.click();
URL.revokeObjectURL(link.href);
};
此时可以发现后端返回的是流文件,前端接到的是乱码。当前端自定义文件名时,可以直接下载
downLoad('https://example.com/api/download', 'test.xlsx')
当采用后端的fileName时,此时要获取后端在 content-disposition 中定义的文件名。
首先调用接口,发现文件名是在请求头content-disposition 中,需要注意的是:虽然我们能看到,但是却拿不到请求头。
如果想让浏览器能访问到其他响应头的话,需要后端在服务器上设置 Access-Control-Expose-Headers
// 后端面大致写法
headers.add("Access-Control-Expose-Headers", "Content-Disposition");
此时可以拿到相关信息,发现是编码的,需要decodeURI 进行解码
const disposition = response.headers.get('Content-Disposition');
const fileName = decodeURI(disposition.split(";")[1].split("filename=")[1])
注:直接在请求方法里是不能获取到请求头信息的,需要对请求进行拦截
request.interceptors.response.use(async (response) => {
const disposition = response.headers.get("Content-Disposition"); // 获取Content-Disposition
return disposition // 当Content-Disposition中有值的时候进行处理,其他请求的响应则放过
? {
blob: await response.blob(), // 将二进制的数据转为blob对象,这一步是异步的因此使用async/await
fileName: decodeURI(disposition.split(";")[1].split("filename=")[1]), // 处理Content-Disposition,获取header中的文件名
}
: response;
});
request 文件
import request from "umi-request";
// 响应拦截
request.interceptors.response.use(async (response) => {
const disposition = response.headers.get("Content-Disposition"); // 获取Content-Disposition
return disposition // 当Content-Disposition中有值的时候进行处理,其他请求的响应则放过
? {
blob: await response.blob(), // 将二进制的数据转为blob对象,这一步是异步的因此使用async/await
fileName: decodeURI(disposition.split(";")[1].split("filename=")[1]), // 处理Content-Disposition,获取header中的文件名
}
: response;
});
export const downLoadExcel = (url) =>
request(url, {
method: "POST",
data: data,
// responseType: "blob", // 注释掉这一段
}).then(data => {
const { blob, fileName } = response;
let link = document.createElement("a");
link.href = URL.createObjectURL( new Blob([blob], { type: "application/vnd.ms-excel" }) );
link.download = fileName;
document.body.appendChild(link);
link.click();
URL.revokeObjectURL(link.href);
document.body.removeChild(link);
});
react 文件
<Buttton onClick={download}> 下载 </Button>
js 文件
async download() {
await downLoadExcel('http://example.com/api/download');
},
原文来自:https://segmentfault.com/a/1190000040808084
PC端上传文件多半用插件,引入flash都没关系,但是移动端要是还用各种冗余的插件估计得被喷死,项目里面需要做图片上传的功能,既然H5已经有相关的接口且兼容性良好,当然优先考虑用H5来实现。
首先我们定义一个input标签type=file、然后我们定义一个jsReadFiles的方法将文件作为参数;当上传文件的时候读取这个文件。图片上传成功,只是图片路径变成了base64编码的形式。
HTML5读取文件主要利用的就是FileReader这个API,它的使用需要从一个构造函数开始,保存文件的关键是生成文件对象,可以使用URL.createObjectURL()方法实现,该方法能返回给定对象的URL,用在<a>标签的href属性上就可以创建可下载的文件链接。
在JavaScript文件中存储敏感数据,不仅是一种错误的实践方式,而且还是一种非常危险的行为,长期以来大家都知道这一点。
比如我写了一个JS文件,这个文件需要调用另外一个JS文件,该如何实现呢?这篇文章主要介绍:在js文件中引入另一个js文件的实现
最近有这样一个需求,就是在HTML页面中有个按钮导出,点击它,将构造一个文档并存储到本地文件系统中。另外还有个按钮,点击它,从本地文件系统中读取一个文件并对内容进行分析。
从 Yarn 横空出世推出 lock 文件以来,已经两年多时间了,npm 也在 5.0 版本加入了类似的功能,lock 文件越来越被开发者们接收和认可。本篇文章想从前端视角探讨一下我们为什么需要 lock 文件,以及它的一些成本与风险,当然其中一些观点对于后端也是适用的
什么是断点续传?就是下载文件时,不必重头开始下载,而是从指定的位置继续下载,这样的功能就叫做断点续传。前端通过FileList对象获取到相应的文件,按照指定的分割方式将大文件分段,然后一段一段地传给后端,后端再按顺序一段段将文件进行拼接。
form表单的enctype属性:规定了form表单数据在发送到服务器时候的编码方式.。application/x-www-form-urlencoded:默认编码方式,multipart/form-data:指定传输数据为二进制数据,例如图片、mp3、文件,text/plain:纯文本的传输。空格转换为“+”,但不支持特殊字符编码。
适用场景: 网络绝对路径的URL文件或图片,不存储到本地,转换成stream,直接使用HTTPClient传送到SpringBoot的服务端,将文件存储下来,并返回一个文件地址。目前分层架构的系统越来越多这种需求,所以记录下来以备不时之需。
内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!