url文件的下载
前言
以前写过一篇《目前前端下载文件的最佳实践》的文章,虽然这个文章是我经过工作实践得出得,但是直到今天我才发现,原来不止如此,根据我目前的知识,可以把文件下载分为两类:
- 接口返回文件流
- 文件下载地址
之前分析的文章仔细一想,其实都在做一个事情:读取文件流再手动转文件进行本地下载
首先我们需要知道,我们的a链接下载其实并没有问题,本来是不需要读取文件流的,但是后端对头信息的了解不多,导致下载文件的链接是一个预览的头信息,这就导致我们a链接无法直接通过点击直接下载,反而是直接打开了这个文件。
这带来的结果就是我们会认为图片啊,pdf这些浏览器可以直接打开的文件,并不会触发下载,而是预览,因为我们很少去怀疑这是不是后端的问题。
为了解决这个问题,我们前端的做法就是通过其它方式读取文件流,然后再自己手动保存文件达到下载文件的效果。具体的做法之前文章就有分享,这里就不多说了。
但是,我们并不需要这么做,一个正宗的文件下载,它的表现应该就是:
- 我们触发一个api请求,后端返回响应,浏览器直接弹出保存文件弹出
- 用户点击a链接下载,后端返回响应,浏览器直接弹出保存文件弹出
而文件流的下载,这种其实会涉及到文件的最新啊,或者权限相关的东西,所以各有千秋,但是正宗的还是上述2点。
怎么做呢?
教程
文件预览
文件的预览,也就是后端错误的文件下载设置,他的头信息有两条:
Content-Disposition
Content-Type
例子:
Content-disposition: inline
Content-Type: image/jpeg
inline表示消息体会以页面的一部分或者整个页面的形式展示,也就是预览,这个需要配合Content-Type一起使用,来告诉浏览器预览的是一个什么文件。
按道理还有一个头信息Content-Length
,他用来表示文件的大小,但是这里只关心下载,所以就不过多赘述。
当我们的下载出现预览时,可以看看响应头是不是这两个。
文件下载(不携带文件名)
头信息设置为:
Content-Disposition: attachment
表示消息体需要被下载,而下载的文件名取决于url,比如你访问的url是:
http://localhost:3000/file/1.jpg
那么文件名就是:1.jpg
而文件格式浏览器会通过Content-Type
来自动添加,比如我请求:
http://localhost:3000/file/1
但是头信息是:
Content-Disposition: attachment
Content-Type: image/jpeg
浏览器还是会识别为:1.jpg
文件下载(带文件名)
Content-Disposition: attachment;filename="filename.jpg"
这个就需要后端动态控制头信息了,比如我设置为:
Content-Disposition: attachment;filename="123.jpg"
访问下载地址:http://localhost:3000/file/1.jpg
下载的文件将是:123.jpg
由于是指定了文件名,所以浏览器不会根据Content-Type
追加文件格式,如果后端的filename的文件格式不对,也会按照这个来进行下载。
koa源码
提供一下个人的测试源码:
server.js
const Koa = require("koa");
const Router = require("koa-router");
const fs = require("fs");
const path = require("path");
const static = require("koa-static");
const send = require("koa-send");
const app = new Koa();
const router = new Router();
router.get("/file/:name", async (ctx) => {
const name = ctx.params.name;
const path = `download/${name}`;
ctx.attachment(path);
ctx.set("Content-disposition", `attachment;filename="123.jpg"`);
await send(ctx, path);
});
app.use(static(path.join(__dirname)));
app.use(router.routes());
app.listen(3000);
download目录与server.js同级。
总结
至此应该可以明白前端下载文件竟然如此简单,再也不用头疼的想办法去下载文件了,我们也可以据理力争前端权益了(明明是后端的问题)。
本文系作者 @木灵鱼儿 原创发布在木灵鱼儿站点。未经许可,禁止转载。
暂无评论数据