成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

node實(shí)現(xiàn)文件下載不得不說的那些事兒

Coly / 1800人閱讀

摘要:如果像本例中這樣的場(chǎng)景會(huì)遇到這樣一個(gè)問題,詳見鏈接當(dāng)請(qǐng)求參數(shù)過長(zhǎng)或?yàn)榱税踩?,就需要用到下載。寫到這里自己都忍不住想錘自己,給自己挖坑不說,這樣來回請(qǐng)求下載,流量,真的是敗家。

這幾天一直在做遠(yuǎn)程文件下載的事,現(xiàn)在總算有了解決,特來記錄一下踩過的坑和想揍自己的心

需求

應(yīng)用場(chǎng)景是這樣的,底層邏輯數(shù)據(jù)請(qǐng)求接口是由Java寫的,也就是說原始文件存在Java服務(wù)端,返回時(shí)有加密措施

由于工作需要,前端獲取數(shù)據(jù)操作需要node服務(wù)器做中間轉(zhuǎn)發(fā)

Java接口使用post方式來請(qǐng)求下載

前端點(diǎn)擊下載后瀏覽器啟用內(nèi)置下載器進(jìn)行下載,并能看到進(jìn)度如下圖所示

先說總結(jié),下附過程
前端GET下載和POST下載的對(duì)比

一般情況下,如果是網(wǎng)盤應(yīng)用或者不涉及多文件下載的場(chǎng)景(如本例中node作為文件服務(wù)器,可以直接與前端交互時(shí)),完全可以通過拼接GET請(qǐng)求url進(jìn)行模擬點(diǎn)擊下載,系統(tǒng)開銷還小,響應(yīng)快。如果像本例中這樣的場(chǎng)景會(huì)遇到這樣一個(gè)問題,詳見鏈接

當(dāng)請(qǐng)求參數(shù)過長(zhǎng)或?yàn)榱税踩托枰玫?b>POST下載。

最終采用的方案

前端通過模擬表單提交POST請(qǐng)求

node端通過piperesponseAresponseB串聯(lián)起來,如responseA.pipe(responseB)

Done

最開始的思路

最開始沒搞清楚怎么用POST請(qǐng)求下載且前端該怎樣接收和處理,關(guān)鍵字node 前端下載搜到的絕大多數(shù)都是用GET鏈接下載,加上剛剛接觸node沒有很好理解流的概念,因此一根筋的想如何通過POST請(qǐng)求轉(zhuǎn)換成GET請(qǐng)求下載,于是自作主張采用了笨辦法,走上了一條差點(diǎn)沒回來的路:

前端點(diǎn)擊下載,發(fā)送post請(qǐng)求Anode

node獲取參數(shù)向Java端發(fā)送post請(qǐng)求B把文件先下載到node本地(Java返回的記為responseA)并用responseB返回前端文件地址文件名

前端獲取到responseB后拼接成get請(qǐng)求模擬a標(biāo)簽點(diǎn)擊去下載node中的文件

下載完成后再將node端對(duì)應(yīng)文件刪除。

寫到這里自己都忍不住想錘自己,給自己挖坑不說,這樣來回請(qǐng)求下載,流量double,真的是敗家。

涉及的知識(shí)點(diǎn)

angular前端訪問node跨域設(shè)置
在前端項(xiàng)目根目錄下新建proxy.conf.json文件,配置接口轉(zhuǎn)發(fā)
{
    "/api": {
        "target" : "http://localhost:3000"http://server端port
    }
}
保存后,配置package.json文件里start命令如下,保存后重新運(yùn)行就好
"start": "ng serve --proxy-config proxy.conf.json",

node如何發(fā)送get/post請(qǐng)求

stream、buffer的概念:文章一 文章二

前端GET下載的三種方式

直接將拼接好的GET請(qǐng)求url賦值給a標(biāo)簽,模擬點(diǎn)擊

先獲取數(shù)據(jù)流存進(jìn)blob對(duì)象,a.href = window.URL.createObjectURL(blob)

每次調(diào)用createObjectUR的時(shí)候,一個(gè)新的URL對(duì)象就被創(chuàng)建了.即使你已經(jīng)為同一個(gè)文件創(chuàng)建過一個(gè)URL. 如果你不再需要這個(gè)對(duì)象,要釋放它,需要使用URL.revokeObjectURL()方法. 當(dāng)頁面被關(guān)閉,瀏覽器會(huì)自動(dòng)釋放它,但是為了最佳性能和內(nèi)存使用,當(dāng)確保不再用得到它的時(shí)候,就應(yīng)該釋放它.

新建一個(gè)隱藏的iframe,src設(shè)置為如上一步的url即可

前端如何接收文件流并下載

原生xhr請(qǐng)求寫法
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請(qǐng)求寫法
axios.post("/api/download_reports",msgArr,{
    responseType:"blob",
    onDownloadProgress (a){
        //監(jiān)聽下載進(jì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)
})

前端如何獲取下載進(jìn)度,并進(jìn)一步完成進(jìn)度條設(shè)置

axios.post("/喵",postData, {
    onUploadProgress (a){
    //上傳進(jìn)度同理
        console.log(a)
    },
    onDownloadProgress (a){
    //控制臺(tái)輸出后,可以發(fā)現(xiàn)我們能夠通過a.loaded*100/a.total來獲得下載進(jìn)度
    //但需注意的是如果node端的responseB沒有設(shè)置"Content-Length"即二進(jìn)制流size的話
    //axios.post此時(shí)獲取到的下載進(jìn)度事件對(duì)象a里lengthComputable為false,進(jìn)而a.total=0
    //進(jìn)而無法獲取百分比進(jìn)度
        console.log(a)
    }
})

前端POST下載的兩種方式

這個(gè)沒有什么好說的,唯一可能要注意的就是表單里input傳參的時(shí)候,如果參數(shù)比較多,可以用JSON.stringify()轉(zhuǎn)換,只向后端發(fā)送一個(gè)字符串就好

以上就是自己對(duì)node實(shí)現(xiàn)文件前端下載的一些理解,如有不妥歡迎交流指正~

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/100252.html

相關(guān)文章

  • webpack那些事兒

    摘要:不管是還是,其實(shí)都是基于實(shí)現(xiàn)的。文件,看名字就知道它是的配置文件。接下來會(huì)向外暴露可以指定是環(huán)境還是環(huán)境。這個(gè)有點(diǎn)不一樣的是他依賴一個(gè)的配置文件。注意這三個(gè)的順序不能錯(cuò),是從右往左執(zhí)行的。到這里,一個(gè)小小的腳手架雛形其實(shí)就有了。不管是vue-cli還是react-sprite,其實(shí)都是基于webpack實(shí)現(xiàn)的。試想,如果沒有腳手架,你自己能搭一個(gè)嗎?看完這篇博客,讓你明白webpak都有些什...

    TNFE 評(píng)論0 收藏0
  • 京東單品頁前端開發(fā)那些不得不說事兒

    摘要:是負(fù)責(zé)展示京東商品的落地頁面。比如京東首頁,正常情況加載完頁面一共有多個(gè)節(jié)點(diǎn),基本上全部用于展示商品信息廣告圖和內(nèi)容布局,頁面上的三方異步服務(wù)也比較少。 原文:https://keelii.github.io/2016/07/31/something-have-to-say-with-JD-item 簡(jiǎn)介 詳情頁也叫做單品頁,域名以「item.jd.com/skuid.html」為格式...

    FleyX 評(píng)論0 收藏0
  • SegmentFault 社區(qū)訪談 | Linxz:只會(huì)寫 CSS 不會(huì)寫 JS “偽”前端

    摘要:所以,現(xiàn)在的我是一個(gè)只會(huì)不會(huì)寫的偽前端。技術(shù)升華環(huán)節(jié)如何理解你的微博簡(jiǎn)介一個(gè)只會(huì)寫不會(huì)寫的偽前端工程師你覺得和學(xué)習(xí)起來各有什么難點(diǎn)呢微博我好久沒去碰了,其實(shí)現(xiàn)在應(yīng)該是寫一個(gè)連都不會(huì)寫,更不會(huì)寫的偽前端工程師。 showImg(https://segmentfault.com/img/bVT0Y4?w=900&h=385); 上周沒和大家見面,是去邀請(qǐng)大佬來訪談了(///▽///)社區(qū)訪...

    libxd 評(píng)論0 收藏0
  • 舒適前端開發(fā)環(huán)境是怎樣一種體驗(yàn)?

    摘要:那我們有沒有辦法不刷新頁面又能看到代碼的更新呢其實(shí)很簡(jiǎn)單,因?yàn)橐呀?jīng)內(nèi)置了這樣的功能,我們只要配置下的注意到上面的代碼,我們?cè)黾恿耍岄_發(fā)環(huán)境有了熱更新的能力。 作者:Nicolas (滬江Web前端)本文為原創(chuàng)文章,轉(zhuǎn)載請(qǐng)注明作者及出處 本文的 webpack 代碼示例根據(jù) webpack 2.7.0 編寫,并在 Mac 上正常運(yùn)行。 去年一篇《在 2016 年學(xué) JavaScript...

    weapon 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<