关于前端form提交后端返回文件流触发欣赏器下载(并发控制) ...

张裕  高级会员 | 2024-8-26 01:29:57 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 213|帖子 213|积分 639

前文介绍过这种文件下载方式,它有好处也有不足的地方。好处是可以充分利用欣赏器自身的资源调理优势,开发只管提交不用关注下载细节,用户可以在欣赏器下载使命中看到下载的状态。不足之处是只能下载到欣赏器设置的默认下载位置,而且JS里不能掌握下载状态。
更为关键的是如果一次下载的文件较多的话,提交了N个请求,如许欣赏器会创建N个标签页,虽然欣赏器自己会调理,下载完后自行关闭这些标签页,但是会带来麋集恐惧,那有没有办法控制下欣赏器下载的使命数(虽然处于下载中的最多6个使命,但是等候的使命也是使命啊)
既然文件下载提交后,无法从欣赏器得到使命下载状态,那么从服务器呢,这个方案是可行的。
前端使命提交后,后端服务器读取本地文件流通过pipeline对接到response,response设置头参数,pipeline完成后回调sse消息发送到前端通知文件下载完成。
  1. app.get('/events', (req,res)=>{
  2.         res.writeHead(200,  { 'Content-Type': 'text/event-stream', 'Connection': 'keep-alive', 'Cache-Control': 'no-cache' });
  3.         res.write(`data: ${JSON.stringify({"msg":"消息服务正常"})}\n\n`);
  4.         let clientid=stringRandom(32, { letters: 'ABCDEF' });
  5.         clients.push({ "clientid":clientid, "uid":req.session.user.userid, "res":res });
  6.         req.on('close', () => { clients = clients.filter(item => (item.clientid != clientid)); });
  7. });
  8. function sendssemsg(jvar)
  9.         clients.forEach(client=>{ if (client.uid==jvar.uid) { client.res.write(`data: ${JSON.stringify(jvar.msg)}\n\n`) } });
  10. }
  11. ...
  12. app.post("/getfile",express.urlencoded({ extended: false }),(req,res)=>{
  13. ...
  14.         res.set({ "Content-Type": "application/octet-stream",  "Content-Disposition": "attachment;filename* = UTF-8''"+fixedEncodeURIComponent(filename.substr(filename.lastIndexOf("/")+1)),"Content-Length": stats.size });
  15.         pipeline(fs.createReadStream(filepath), res, (err) => {
  16.                 if (err) console.log("下载出错")
  17.                 else sendssemsg({"uid":userid,"msg":filename+" 下载完成"})
  18.                 });
  19.         ...
复制代码
通过sse发送下载效果,效率最好
前端收到相应的sse消息,就可以处理下载使命队列操纵了
  1.         function downloadfile(filename) {
  2.                 let form=$("#formp");
  3.                 $("input[name=filename]").attr("value",filename);
  4.                 form.submit();
  5.                 }
  6.        
  7.         var indownloading=0;
  8.         const evtSource = new EventSource("/events");
  9.         evtSource.addEventListener('message', function(event) {
  10.                 //let jvar=JSON.parse(event.data);
  11.                 indownloading-=1;
  12.                 if (waitinglist.length>0) {
  13.                         indownloading+=1;
  14.                         downloadfile(waitinglist.shift());
  15.                         }
  16.                 })
  17.         let indownloading=0;
  18.         let taskLimit=navigator.hardwareConcurrency;
  19.         while ((indownloading<tasklimit)&&(waitinglist.length>0)) {
  20.                 indownloading+=1;
  21.                 downloadfile(waitinglist.shift());
  22.                 }
复制代码
  1. <form name="formp" id="formp" action="/getfile" method="post" target="_blank" rel="noopener noreferrer">
  2. <input name="filename" value="">
  3. </form>
复制代码
如许效果就是下载使命控制在CPU核数,欣赏器上看到的下载标签也不会太多,视觉观感上对用户更友爱一些。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

张裕

高级会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表