后端代码
async downloadFile() { const { ctx } = this; const body = ctx.request.body; const { id } = body; const fileRecord = await ctx.model.File.findOne({ where: { id }, attributes: ['path', 'suffix', 'md5_code', 'mime_type'], raw: true, }); const file = fileRecord.path; try { fs.accessSync(file, fs.constants.F_OK); } catch (err) { console.log(`${file} does not exist`); return ctx.fail({ msg: '文件不存在' }); } const reader = fs.createReadStream(file); const streamToBuffer = (stream) => { return new Promise((resolve, reject) => { const buffers = []; stream.on('error', reject); stream.on('data', (data) => buffers.push(data)); stream.on('end', () => resolve(Buffer.concat(buffers))); }); }; const content = await streamToBuffer(reader); return ctx.success({ result: { content, mime_type: fileRecord.mime_type, suffix: fileRecord.suffix, md5_code: fileRecord.md5_code, }, }); }
实例json fileRecord { path: 'D:\\app\\public\\upload\\20200525\\15903898530878733.jpg', suffix: '.jpg', md5_code: '15903898530878733', mime_type: 'image/jpeg' }
返回结果
前端代码
export const downloadFile = async id => { let res = await axios.post("/api/file/download", { id });
const data = res.result; let ab = new ArrayBuffer(data.content.data.length); let view = new Uint8Array(ab); for (var i = 0; i < data.content.data.length; ++i) { view[i] = data.content.data[i]; }
或者
let ab = Buffer.from(data.content, "binary");
const blob = new Blob([ab], { type: data.mime_type }); const filename = data.md5_code + data.suffix; if (window.navigator.msSaveOrOpenBlob) { navigator.msSaveBlob(blob, filename); } else { const link = document.createElement("a"); const body = document.querySelector("body"); link.href = window.URL.createObjectURL(blob); // 创建对象url link.download = filename; // fix Firefox link.style.display = "none"; body.appendChild(link); link.click(); body.removeChild(link); window.URL.revokeObjectURL(link.href); // 通过调用 URL.createObjectURL() 创建的 URL 对象 } };
Nodejs中ArrayBuffer 与 Buffer的互相转换(参考 https://www.jianshu.com/p/2b57264d1327)
Buffer => ArrayBuffer
function toArrayBuffer(buf) { var ab = new ArrayBuffer(buf.length); var view = new Uint8Array(ab); for (var i = 0; i < buf.length; ++i) { view[i] = buf[i]; } return ab; }
ArrayBuffer => Buffer
function toBuffer(ab) { var buf = new Buffer(ab.byteLength); var view = new Uint8Array(ab); for (var i = 0; i < buf.length; ++i) { buf[i] = view[i]; } return buf; }