前端學(xué)習(xí)隨記の下載上傳篇 —— 下載篇

前端學(xué)習(xí)隨記の下載上傳篇 —— 下載篇

閑言: 懶懶懶!I亍香缺!好長(zhǎng)時(shí)間不寫文章了,一直出差魔都歇僧,學(xué)習(xí)一些其他知識(shí)開發(fā)項(xiàng)目图张,也時(shí)不時(shí)的空閑時(shí)間深度學(xué)習(xí)一些前端基礎(chǔ)知識(shí)锋拖。好吧,不找理由祸轮,就是懶哇哈哈(????)兽埃。

demo代碼:https://github.com/NARUTOne/DownAndUp.git

參考傳送門:
http://www.cnblogs.com/voiphudong/p/3284724.html
https://scarletsky.github.io/2016/07/03/download-file-using-javascript/#參考資料
https://developer.mozilla.org/zh-CN/docs/Web/API/FileSystem

引言###

上傳下載一直是項(xiàng)目上非常常見的需求,也是對(duì)于我這種前端小白來(lái)說(shuō)一直隱隱犯怵的地方适袜,不太熟悉柄错,加上項(xiàng)目上用過(guò)一次,同事朋友也問過(guò)遇到過(guò)苦酱,所以打算好好惡補(bǔ)這塊↖(ω)↗售貌。本篇先說(shuō)下下載,上傳留著下篇來(lái)說(shuō)疫萤,歡迎關(guān)注留bug.

幾種下載方式

前后端下載方式原理簡(jiǎn)述:

1)標(biāo)準(zhǔn)URL下載方式:?可以通過(guò)在web頁(yè)面中嵌入 url超級(jí)鏈接颂跨,標(biāo)準(zhǔn)的HTTP GET請(qǐng)求。對(duì)于服務(wù)器端web根目錄有一個(gè)test.zip的文件扯饶。此種方法的弊端是完全暴露了文件test.zip的網(wǎng)站路徑恒削,而且動(dòng)態(tài)性不夠靈活。

2)通過(guò)服務(wù)器端腳本向?yàn)g覽器方(stdout)輸出二進(jìn)制流的方式下載:?上述方法可以在服務(wù)器端 通過(guò) 腳本程序 download.php 尾序,并且根據(jù)傳入的查詢字符串f=test.zip定位服務(wù)器上文件系統(tǒng)test.zip的路徑钓丰,然后按二進(jìn)制流的方式發(fā)送給客戶端瀏覽器,那么客戶端瀏覽器就會(huì)彈出一個(gè)“下載對(duì)話框”了每币。

form 表單下載

POST的URL下載鏈接携丁,可以通過(guò)設(shè)置form表單的action 以及 表單元素值來(lái)完成下載。

function downLoad () {
  var form = document.createElement('form');   //定義一個(gè)form表單
  form.style = 'display:none';   //下面為在form表單中添加查詢參數(shù)
  form.target = '';
  form.method = 'post';
  form.action = url;//下載接口

  var input1 = document.createElement('input');
  input1.type = 'hidden';
  Input1.name = 'exportData';
  input1.value = (new Date()).getMilliseconds(); 

  document.body.appendChild(form)  //將表單放置在web中
  form.appendChild(input1);   //將查詢參數(shù)控件提交到表單上
  form.submit();   //表單提交
}

iframe

iframe有一個(gè)src屬性脯爪,其本質(zhì)就是發(fā)送http請(qǐng)求则北,GET一個(gè)頁(yè)面或者數(shù)據(jù),可以通過(guò)一個(gè)動(dòng)態(tài)生成的隱藏的iframe來(lái)得到下載的二進(jìn)制文件。

function download(){
  var IFrameRequest=document.createElement("iframe");
  IFrameRequest.id="IFrameRequest";
  IFrameRequest.src="/test.zip";
  IFrameRequest.style.display="none";
  document.body.appendChild(IFrameRequest);
}

HTML5のdownload屬性

由于瀏覽器的安全策略的限制痕慢,我們通常只能通過(guò)一個(gè)額外的頁(yè)面,訪問某個(gè)文件的 url 來(lái)實(shí)現(xiàn)下載功能涌矢,但是這種用戶體驗(yàn)非常不好掖举。HTML 5 里面為 a 標(biāo)簽添加了一個(gè) download 的屬性,我們可以輕易的利用它來(lái)實(shí)現(xiàn)下載功能娜庇。

<a href="http://somehost/somefile.zip" download="filename.zip">Download file</a>

a標(biāo)簽添加 download 屬性塔次,我們點(diǎn)擊這個(gè)鏈接的時(shí)候就會(huì)自動(dòng)下載文件了~
順便說(shuō)下,download 的屬性值是可選的名秀,它用來(lái)指定下載文件的文件名励负。像上面的例子中,我們下載到本地的文件名就會(huì)是 filename.zip 拉匕得,如果不指定的話继榆,它就會(huì)是 somefile.zip 這個(gè)名字啦巾表!

當(dāng)然,我們還可以動(dòng)態(tài)創(chuàng)建a標(biāo)簽實(shí)現(xiàn)下載:

function download() {
  var a = document.createElement('a');
  var url = window.URL.createObjectURL(blob);
  var filename = 'what-you-want.txt';
  a.href = url;
  a.download = filename;
  a.click();
  window.URL.revokeObjectURL(url);
}

window.URL 里面有兩個(gè)方法:
createObjectURL 用 blob 對(duì)象來(lái)創(chuàng)建一個(gè) object URL(它是一個(gè) DOMString)略吨,我們可以用這個(gè) object URL 來(lái)表示某個(gè) blob 對(duì)象集币,這個(gè) object URL 可以用在 href 和 src 之類的屬性上。
revokeObjectURL 釋放由 createObjectURL 創(chuàng)建的 object URL翠忠,當(dāng)該 object URL 不需要的時(shí)候鞠苟,我們要主動(dòng)調(diào)用這個(gè)方法來(lái)獲取最佳性能和內(nèi)存使用。
當(dāng)然秽之,如果你沒有blob對(duì)象的url,也可以不用window.URL当娱,直接使用下載地址url。

HTML5のFileSystem

由于這種方法目前大多數(shù)瀏覽器不支持考榨,僅僅chrome支持跨细,具體方式可以查看大神們的文章,我就不搬運(yùn)了董虱。(????)
https://imququ.com/post/a-downloader-with-filesystem-api.html

其他方式

Window.open(url):這種方式在目前的網(wǎng)絡(luò)環(huán)境及安全限制下被攔截已經(jīng)不太好使了扼鞋,主要用來(lái)是打開新窗口下載。

var new_window = null;
function downLoad () {
  var isSure=confirm("是否下載")
  if (isSure){
    new_window = window.open()
    new_window.location.;
    document.getElementById('result').innerHTML = "You downLoad OK!"
  }
  else{
    document.getElementById('result').innerHTML = "You pressed Cancel!"
  }
}
function closeDownLoad() {
  new_window  && new_window.close();
}

//使用a鏈接target='_blank'愤诱,則不會(huì)攔截下載
function AdownLoad() {
  var url = 'https://github.com/WZOnePiece/study-draggable/archive/master.zip';
  var a = document.createElement("a");
  a.setAttribute("href", url);
  a.setAttribute("target", "_blank");
  a.setAttribute("id", "camnpr");
  document.body.appendChild(a);
  a.click();
}

這里主要是用window.open 打開窗口云头,接著使用location.href = url進(jìn)行重定向避免攔截進(jìn)行下載。

補(bǔ)充知識(shí)

Blob 對(duì)象

Blob 全稱是 Binary large object淫半,它表示一個(gè)類文件對(duì)象溃槐,可以用它來(lái)表示一個(gè)文件。根據(jù) MDN 上面的說(shuō)法科吭,F(xiàn)ile API 也是基于 blob 來(lái)實(shí)現(xiàn)的昏滴。

構(gòu)建 blob 的方式就是通過(guò)服務(wù)器返回的文件來(lái)創(chuàng)建 blob ,采用File API及Fetch API对人。

fetch('http://somehost/somefile.zip').then(res => res.blob().then(blob => {
  var a = document.createElement('a');
  var url = window.URL.createObjectURL(blob);
  var filename = 'myfile.zip';
  a.href = url;
  a.download = filename;
  a.click();
  window.URL.revokeObjectURL(url);
}))

注意:Fetch API 目前瀏覽器支持不好谣殊,詳情看https://developer.mozilla.org/zh-CN/docs/Web/API/Fetch_API/Using_Fetch
File API的詳細(xì)介紹:https://developer.mozilla.org/zh-CN/docs/Using_files_from_web_applications
可以利用fetch配合reader對(duì)象來(lái)實(shí)現(xiàn)進(jìn)度條功能

限制

1、不同瀏覽器對(duì) blob 對(duì)象有不同的限制

Supported browsers

Browser Constructs as Filenames Max Blob Size Dependencies
Firefox 20+ Blob Yes 800 MiB None
Firefox < 20 data: URI No n/a Blob.js
Chrome Blob Yes [500 MiB][3] None
Chrome for Android Blob Yes [500 MiB][3] None
Edge Blob Yes ? None
IE 10+ Blob Yes 600 MiB None
Opera 15+ Blob Yes 500 MiB None
Opera < 15 data: URI No n/a Blob.js
Safari 6.1+* Blob No ? None
Safari < 6 data: URI No n/a Blob.js

2牺弄、構(gòu)建完 blob 對(duì)象后才會(huì)轉(zhuǎn)換成文件姻几。

文件大點(diǎn)的話,要等到下載完文件之后才能構(gòu)建 blob 對(duì)象势告,再轉(zhuǎn)化成文件蛇捌,頁(yè)面顯示上不太友好,沒有提示咱台。這時(shí)建議采用a標(biāo)簽络拌,防止用戶的錯(cuò)誤認(rèn)知造成重復(fù)點(diǎn)擊下載,資源浪費(fèi)回溺。

服務(wù)器出錯(cuò)

  • 1春贸、window.open(url)

打開一個(gè)帶錯(cuò)誤信息的頁(yè)面

  • 2混萝、window.location.href

頁(yè)面將跳轉(zhuǎn)到一個(gè)錯(cuò)誤頁(yè)面

  • 3、iframe

用戶感知不到任何變化

  • 4祥诽、a標(biāo)簽

直接出現(xiàn) 下載失敗

當(dāng)然譬圣,如果response header里有content-disposition字段的話,瀏覽器都會(huì)下載一個(gè)帶錯(cuò)誤信息的文件雄坪。這時(shí)候厘熟,其實(shí)我們可以多發(fā)一個(gè)ajax/fetch請(qǐng)求,先檢測(cè)下接口狀態(tài)维哈,然后再取做下載邏輯绳姨。但這樣就對(duì)服務(wù)器造成了額外的開銷。

這樣的體驗(yàn)都不太好阔挠,作為一個(gè)追求極致體驗(yàn)的程序猿飘庄,我們應(yīng)該重新思考下,如何提升用戶體驗(yàn)购撼。

結(jié)語(yǔ)##

O(∩_∩)O跪削,這篇下載篇就這樣簡(jiǎn)單介紹下,至于還有其他的方式迂求,歡迎留言告知碾盐;代碼及描述上有bug也希望不吝指出。謝謝哈揩局!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末毫玖,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子凌盯,更是在濱河造成了極大的恐慌付枫,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,692評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件驰怎,死亡現(xiàn)場(chǎng)離奇詭異阐滩,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)县忌,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,482評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門叶眉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人芹枷,你說(shuō)我怎么就攤上這事×ぃ” “怎么了鸳慈?”我有些...
    開封第一講書人閱讀 162,995評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)喧伞。 經(jīng)常有香客問我走芋,道長(zhǎng)绩郎,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,223評(píng)論 1 292
  • 正文 為了忘掉前任翁逞,我火速辦了婚禮肋杖,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘挖函。我一直安慰自己状植,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,245評(píng)論 6 388
  • 文/花漫 我一把揭開白布怨喘。 她就那樣靜靜地躺著津畸,像睡著了一般。 火紅的嫁衣襯著肌膚如雪必怜。 梳的紋絲不亂的頭發(fā)上肉拓,一...
    開封第一講書人閱讀 51,208評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音梳庆,去河邊找鬼暖途。 笑死,一個(gè)胖子當(dāng)著我的面吹牛膏执,可吹牛的內(nèi)容都是我干的驻售。 我是一名探鬼主播,決...
    沈念sama閱讀 40,091評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼胧后,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼芋浮!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起壳快,我...
    開封第一講書人閱讀 38,929評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤纸巷,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后眶痰,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體瘤旨,經(jīng)...
    沈念sama閱讀 45,346評(píng)論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,570評(píng)論 2 333
  • 正文 我和宋清朗相戀三年竖伯,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了存哲。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,739評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡七婴,死狀恐怖祟偷,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情打厘,我是刑警寧澤修肠,帶...
    沈念sama閱讀 35,437評(píng)論 5 344
  • 正文 年R本政府宣布,位于F島的核電站户盯,受9級(jí)特大地震影響嵌施,放射性物質(zhì)發(fā)生泄漏饲化。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,037評(píng)論 3 326
  • 文/蒙蒙 一吗伤、第九天 我趴在偏房一處隱蔽的房頂上張望吃靠。 院中可真熱鬧,春花似錦足淆、人聲如沸巢块。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,677評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)夕冲。三九已至,卻和暖如春裂逐,著一層夾襖步出監(jiān)牢的瞬間歹鱼,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,833評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工卜高, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留弥姻,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,760評(píng)論 2 369
  • 正文 我出身青樓掺涛,卻偏偏與公主長(zhǎng)得像庭敦,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子薪缆,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,647評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 閑言: 上篇我們學(xué)習(xí)了一些下載的js前端方式秧廉,這篇來(lái)講講上傳篇。這也是在項(xiàng)目需求中很常見的O(∩_∩)O拣帽。 dem...
    迷緣火葉閱讀 550評(píng)論 0 1
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理疼电,服務(wù)發(fā)現(xiàn),斷路器减拭,智...
    卡卡羅2017閱讀 134,652評(píng)論 18 139
  • 第一次做內(nèi)購(gòu)蔽豺,審核失敗。拧粪。修陡。ios內(nèi)購(gòu) 元數(shù)據(jù)丟失 審核信息里的審核屏幕快照跟備注要填寫,不然就失敗的可霎。第一次用I...
    工匠良辰閱讀 11,701評(píng)論 5 2
  • 02 “二位魄鸦,睡得可好?” 一股飛速旋轉(zhuǎn)的黑煙席卷而來(lái)癣朗。少年号杏,老者,還有仆人,三人居高臨下地現(xiàn)身于我們面前盾致。 “明...
    井水花生閱讀 954評(píng)論 5 9
  • 迭代器是一個(gè)對(duì)象月匣,用于將容器對(duì)象作為列表遍歷杉编。在 JavaScript 中胚迫,迭代器對(duì)象不是一個(gè)獨(dú)立的內(nèi)置對(duì)象漏隐,而是...
    趙然228閱讀 355評(píng)論 0 1