实际开发项目,经常会遇到文件相关的接口,比如文件上传和下载,这里针对前端总结一些 mock 文件接口在本地调试的方法
文件下载
基于Node.js
快速启动一个 web 服务,借助中间件 koa-send
实现下载功能
const path = require('path');
const Koa = require('koa');
const staticServe = require('koa-static');
const router = require('koa-router')();
const send = require('koa-send');
const app = new Koa();
const staticPath = '/static';
const absolutePath = path.join(__dirname + staticPath);
// 指定静态目录
app.use(staticServe(absolutePath));
app.use(async (ctx) => {
ctx.body = 'hello word'
});
router.get('/file/:name', async (ctx){
const name = ctx.params.name;
const path = `static/${name}`;
ctx.attachment(path);
await send(ctx, path);
})
app.use(router.routes()).use(router.allowedMethods());
app.listen(3000, () => {
console.log('server is listening in 3000...');
})
koa-send 内部其实用了 fs.createReadStream
,以块的形式发送出去,这样前端可以更快地接收数据。fs.readFile
还会将整个文件加载到内存中
前端调用接口
fetch
fetch()
.then((res) => {
return res.blob();
// txt、base64或其他文本类的文件可用以下方式解析
// return res.text()
})
.then((res) => {
// 下载文件示例
let url = URL.createObjectURL(new Blob([res]));
let link = document.createElement("a");
link.style.display = "none";
link.href = url;
link.download = `image.png`;
document.body.appendChild(link);
link.click();
// 解析base64
// const data = window.atob(res)
});
如果是 axios,需要额外配置 responseType: 'blob'
,其实也就是 XMLHttpRequest 的配置
类似的中间件有 koa-sendfile
,主要是解决中文编码的问题
文件上传
前端主要是通过表单来上传文件,但是文件数据在服务器端并不能像普通参数一样通过 ctx.request.body 获取。这里我们可以借助 koa-body
实现上传功能,该中间件的作用主要是将文件数据拼接到 ctx.request.body.files.file
const koaBody = require('koa-body');
// ...
app.use(koaBody({
multipart: true,
// formidable: {
// 默认限制只有2M,超过会报错
// maxFileSize: 100*1024*1024
// }
}));
router.post('/upload', async (ctx){
const file = ctx.request.body.files.file;
const reader = fs.createReadStream(file.path);
const upStream = fs.createWriteStream(`upload/${file.name}`);
reader.pipe(upStream);
return ctx.body = '上传成功';
})
// ...
前端拼接文件数据
const formData = new FormData();
formData.append("file", input.files[0]);
formData.append("user", "Lucas");
fetch(url, {
method: "POST",
body: formData,
});
不起 web 服务
纯 js 由于浏览器的安全考虑是没法直接操作文件的,如果不想启动服务,还可以借助文件选择或拖拽来模拟读取文件接口。以下示例基于 React Hook(只是提供获取文件的方法,具体使用还需要自行验证)
文件选择:
const fileInputRef = useRef();
// ...
// 监听文件选择
fileInputRef.current.onchange = function (event) {
const file = event.target.files[0];
};
// ...
<input type="file" name="test" ref={fileInputRef} />;
拖拽:
const dragDropRef = useRef();
// ...
// 监听
dragDropRef.current.addEventListener(
"drop",
function (event) {
const file = event.dataTransfer.files[0];
},
false
);
// ...
<div ref={dragDropRef} />;
更多前端处理二进制数据的方法可以参考 https://blog.zhouweibin.top/js/%E4%BA%8C%E8%BF%9B%E5%88%B6%E6%95%B0%E6%8D%AE/