背景:
前端用a標簽發起下載文檔的get請求
node中間層接到get請求后將請求轉發到java后端
java后端返回文檔流傳遞給node中間層
好處:
后端的java業務邏輯層接口、數據庫不向外部暴露,node中間層進行安全驗證及請求轉發
1.前端發起請求
<a download={`${filename}文件.doc`} href={`${domain}/api/word/download?a=${fileid}&b=${filename}> 下載文件 </a>
2.koa 中間層轉發
router.get('/word/download',async (ctx,next)=>{ let {a,b,date} = ctx.query; date = date || timeStamp2String(false,'short'); let file = await request({ uri:'word', qs:{ orgNo:a } }); let s = new Readable; s.push(file); s.push(null); let docx = 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'; let doc = 'application/msword'; ctx.set('content-type',docx); ctx.set('content-disposition',`attachment;filename*=UTF-8''${encodeURIComponent(b)}.docx`); ctx.body = s; });
3.request方法請求java后端
import request from 'request-promise'; function reqGetStreamData(params){ let {uri,qs} = params; return new Promise((resolve,reject)=>{ request({ uri:`${domain}api/jgs/${uri}`, qs, encoding:null, headers: { 'User-Agent': 'Request-Promise', 'Content-type':docx }, json: false }).then(data => { resolve(data); }, err => { let errData = { status:1, data:err, statusInfo:'失敗' } reject(errData); }).catch(err => { let obj = { status: 1, data: err, statusInfo: '未知錯誤!' }; reject(obj); }); }); }
原理就是:將java后端返回的文件流被request轉換為buffer對象,然后用stream.Readable將buffer對象轉換為流,直接返回給前端即可