摘要:如果像本例中這樣的場景會遇到這樣一個問題,詳見鏈接當(dāng)請求參數(shù)過長或為了安全,就需要用到下載。寫到這里自己都忍不住想錘自己,給自己挖坑不說,這樣來回請求下載,流量,真的是敗家。
這幾天一直在做遠程文件下載的事,現(xiàn)在總算有了解決,特來記錄一下踩過的坑和想揍自己的心
需求應(yīng)用場景是這樣的,底層邏輯數(shù)據(jù)請求接口是由Java寫的,也就是說原始文件存在Java服務(wù)端,返回時有加密措施
由于工作需要,前端獲取數(shù)據(jù)操作需要node服務(wù)器做中間轉(zhuǎn)發(fā)
Java接口使用post方式來請求下載
前端點擊下載后瀏覽器啟用內(nèi)置下載器進行下載,并能看到進度如下圖所示
先說總結(jié),下附過程前端GET下載和POST下載的對比
一般情況下,如果是網(wǎng)盤應(yīng)用或者不涉及多文件下載的場景(如本例中node作為文件服務(wù)器,可以直接與前端交互時),完全可以通過拼接GET請求url進行模擬點擊下載,系統(tǒng)開銷還小,響應(yīng)快。如果像本例中這樣的場景會遇到這樣一個問題,詳見鏈接
當(dāng)請求參數(shù)過長或為了安全,就需要用到POST下載。
最終采用的方案前端通過模擬表單提交POST請求
node端通過pipe將responseA和responseB串聯(lián)起來,如responseA.pipe(responseB)
Done
最開始的思路最開始沒搞清楚怎么用POST請求下載且前端該怎樣接收和處理,關(guān)鍵字node 前端下載搜到的絕大多數(shù)都是用GET鏈接下載,加上剛剛接觸node沒有很好理解流的概念,因此一根筋的想如何通過POST請求轉(zhuǎn)換成GET請求下載,于是自作主張采用了笨辦法,走上了一條差點沒回來的路:
前端點擊下載,發(fā)送post請求A給node
由node獲取參數(shù)向Java端發(fā)送post請求B把文件先下載到node本地(Java返回的記為responseA)并用responseB返回前端文件地址和文件名
前端獲取到responseB后拼接成get請求模擬a標(biāo)簽點擊去下載node中的文件
下載完成后再將node端對應(yīng)文件刪除。
寫到這里自己都忍不住想錘自己,給自己挖坑不說,這樣來回請求下載,流量double,真的是敗家。
涉及的知識點
在前端項目根目錄下新建proxy.conf.json文件,配置接口轉(zhuǎn)發(fā)
{ "/api": { "target" : "http://localhost:3000"http://server端port } }
保存后,配置package.json文件里start命令如下,保存后重新運行就好
"start": "ng serve --proxy-config proxy.conf.json",
node如何發(fā)送get/post請求
stream、buffer的概念:文章一 文章二
前端GET下載的三種方式
直接將拼接好的GET請求url賦值給a標(biāo)簽,模擬點擊
先獲取數(shù)據(jù)流存進blob對象,a.href = window.URL.createObjectURL(blob)
每次調(diào)用createObjectUR的時候,一個新的URL對象就被創(chuàng)建了.即使你已經(jīng)為同一個文件創(chuàng)建過一個URL. 如果你不再需要這個對象,要釋放它,需要使用URL.revokeObjectURL()方法. 當(dāng)頁面被關(guān)閉,瀏覽器會自動釋放它,但是為了最佳性能和內(nèi)存使用,當(dāng)確保不再用得到它的時候,就應(yīng)該釋放它.
新建一個隱藏的iframe,src設(shè)置為如上一步的url即可
前端如何接收文件流并下載
原生xhr請求寫法
var xhr = new XMLHttpRequest(); xhr.open("get", url, true); xhr.responseType = "blob"; xhr.onload = function() { if (this.status == 200) { var blob = this.response; var img = document.createElement("img"); img.onload = function(e) { window.URL.revokeObjectURL(img.src); }; img.src = window.URL.createObjectURL(blob); $("#imgcontainer").html(img); } } xhr.send();
axios請求寫法
axios.post("/api/download_reports",msgArr,{ responseType:"blob", onDownloadProgress (a){ //監(jiān)聽下載進度 if(a.lengthComputable){ let percent = (a.loaded*100/a.total).toFixed(2) console.log(percent) $("#percent").html(tempLoaded) } } }) .then(response => { console.log(response) if(response.status == 200){ const blob = new Blob([response.data],{type: "application/octet-stream"}); const url = window.URL.createObjectURL(blob); const a = document.createElement("a"); a.href = url; a.download = baseName+".zip"; document.body.appendChild(a); a.click(); document.body.removeChild(a); window.URL.revokeObjectURL(url); } }) .catch(error => { console.log(error) })
前端如何獲取下載進度,并進一步完成進度條設(shè)置
axios.post("/喵",postData, { onUploadProgress (a){ //上傳進度同理 console.log(a) }, onDownloadProgress (a){ //控制臺輸出后,可以發(fā)現(xiàn)我們能夠通過a.loaded*100/a.total來獲得下載進度 //但需注意的是如果node端的responseB沒有設(shè)置"Content-Length"即二進制流size的話 //axios.post此時獲取到的下載進度事件對象a里lengthComputable為false,進而a.total=0 //進而無法獲取百分比進度 console.log(a) } })
前端POST下載的兩種方式
這個沒有什么好說的,唯一可能要注意的就是表單里input傳參的時候,如果參數(shù)比較多,可以用JSON.stringify()轉(zhuǎn)換,只向后端發(fā)送一個字符串就好
以上就是自己對node實現(xiàn)文件前端下載的一些理解,如有不妥歡迎交流指正~
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/100252.html
摘要:不管是還是,其實都是基于實現(xiàn)的。文件,看名字就知道它是的配置文件。接下來會向外暴露可以指定是環(huán)境還是環(huán)境。這個有點不一樣的是他依賴一個的配置文件。注意這三個的順序不能錯,是從右往左執(zhí)行的。到這里,一個小小的腳手架雛形其實就有了。不管是vue-cli還是react-sprite,其實都是基于webpack實現(xiàn)的。試想,如果沒有腳手架,你自己能搭一個嗎?看完這篇博客,讓你明白webpak都有些什...
摘要:是負責(zé)展示京東商品的落地頁面。比如京東首頁,正常情況加載完頁面一共有多個節(jié)點,基本上全部用于展示商品信息廣告圖和內(nèi)容布局,頁面上的三方異步服務(wù)也比較少。 原文:https://keelii.github.io/2016/07/31/something-have-to-say-with-JD-item 簡介 詳情頁也叫做單品頁,域名以「item.jd.com/skuid.html」為格式...
摘要:所以,現(xiàn)在的我是一個只會不會寫的偽前端。技術(shù)升華環(huán)節(jié)如何理解你的微博簡介一個只會寫不會寫的偽前端工程師你覺得和學(xué)習(xí)起來各有什么難點呢微博我好久沒去碰了,其實現(xiàn)在應(yīng)該是寫一個連都不會寫,更不會寫的偽前端工程師。 showImg(https://segmentfault.com/img/bVT0Y4?w=900&h=385); 上周沒和大家見面,是去邀請大佬來訪談了(///▽///)社區(qū)訪...
摘要:那我們有沒有辦法不刷新頁面又能看到代碼的更新呢其實很簡單,因為已經(jīng)內(nèi)置了這樣的功能,我們只要配置下的注意到上面的代碼,我們增加了,讓開發(fā)環(huán)境有了熱更新的能力。 作者:Nicolas (滬江Web前端)本文為原創(chuàng)文章,轉(zhuǎn)載請注明作者及出處 本文的 webpack 代碼示例根據(jù) webpack 2.7.0 編寫,并在 Mac 上正常運行。 去年一篇《在 2016 年學(xué) JavaScript...
閱讀 1914·2021-09-23 11:21
閱讀 1701·2019-08-29 17:27
閱讀 1059·2019-08-29 17:03
閱讀 728·2019-08-29 15:07
閱讀 1922·2019-08-29 11:13
閱讀 2381·2019-08-26 12:14
閱讀 922·2019-08-26 11:52
閱讀 1733·2019-08-23 17:09