前端下載的實現

前端很多項目中,都有文件下載的需求,特別是JS生成文件內容,然后讓瀏覽器執行下載操作(例如在線圖片編輯、在線代碼編輯、iPresst等)。但受限于瀏覽器,很多情況下我們都只能給出個鏈接,讓用戶點擊打開-》另存為。如下面這個鏈接:
<a href=”file.js”>file.js</a>
用戶點擊這個鏈接的時候,瀏覽器會打開并顯示鏈接指向的文件內容,顯然,這并沒有實現我們的需求。HTML5中給a標簽增加了一個download屬性,只要有這個屬性,點擊這個鏈接時瀏覽器就不在打開鏈接指向的文件,而是改為下載(目前只有chrome、firefox和opera支持)。下載時會直接使用鏈接的名字來作為文件名,但是是可以改的,只要給download加上想要的文件名即可,如:download=“not-a-file.js”。Not enough!但是這樣還不夠,以上的方法只適合用在文件是在服務器上的情況。如果在瀏覽器端js生成的內容,想讓瀏覽器進行下載要如何辦到呢?其實還是有辦法辦到的,相信很多人都多少聽過了DataURI這個詞,比較常見的就是圖片的src,如:
<img src=”data:image/gif;base64,R0lGOXXXXX">
DataURI的解釋可以移步這里,本人就不在解釋了。那么,現在要將js生成的內容進行下載就有法可依了。封裝成一個方法如下:JavaScript
function downloadFile(aLink, fileName, content){aLink.download = fileName;aLink.href = "data:text/plain," + content;
}
調用downloadFile之后,用戶點擊鏈接,就能觸發瀏覽器下載。Not enough!但是,還不夠,上面的辦法有兩個硬傷,會導致流失很多懶人美眉:下載的文件類型限制死了,美眉要下載處理后的果照怎么辦?下載還要再點擊一下,太麻煩啦。要解決文件類型的問題,可以用瀏覽器的新API(URL.createObjectURL)來解決問題,URL.createObjectURL通常都是用來創建圖片的DataURI用來顯示圖片,這里用來下載文件,讓瀏覽器來幫我們設定好文件類型。URL.createObjectURL的參數是File對象或者Blob對象,File對象也就是通過input[type=file]選擇的文件,Blob對象是二進制大對象,詳細說明可參考這里。現在,我們只要用content創建一個ObjectURL并賦值給aLink即可解決文件類型的限制問題。文件的自動下載也挺好辦,自己構建一個UI點擊事件,再自動觸發下,就能實現自動下載啦。現在來看看最終代碼:JavaScript/*let url = new URL('https://example.com?foo=1&bar=2');console.log(url);URL {href:"https://example.com/?foo=1&bar=2", origin: "https://example.com", protocol: "https:", username: "", password: "", …}hash:""host:"example.com"hostname:"example.com"href:"https://example.com/?foo=1&bar=2"origin:"https://example.com"password:""pathname:"/"port:""protocol:"https:"search:"?foo=1&bar=2"searchParams:URLSearchParams {}username:""}/*arrayObject.slice(start,end)返回一個新的數組,包含從start到end(不包括該元素)的 arrayObject 中的元素。
*/
/*去掉?,剩下let params = new URLSearchParams(url.search.slice(1));//添加第二個foo搜索參數。params.append('foo', 4);//查詢字符串變成: 'foo=1&bar=2&foo=4'
*///下載功能實現:用iframes,其實就是通過iframes給后臺發請求,讓后臺實現具體下載
import axios from 'axios';
export const baseURL = '/service';
export function getFileName(headers) {//headers['content-disposition']的屬性值中的'attachment; filename='用空格代替,拿到file的值return headers['content-disposition'].replace('attachment; filename=', '');
}
export function downloadData(url,params) {//URLSearchParams 接口定義了一些實用的方法來處理 URL 的查詢字符串var searchParams = new URLSearchParams();url = baseURL + url;for (let key of Object.keys(params)) {searchParams.append(key, encodeURIComponent(params[key]));}document.querySelector('#downloadIframe').setAttribute('src', url + '?' + searchParams)
}//下載功能的實現:用a.download, 后臺返回的 res.data 必須是 blob 對象
export function download(res) {var a = document.createElement('a');//URL.createObjectURL通常都是用來創建圖片的DataURI用來顯示圖片,這里用來下載文件,讓瀏覽器來幫我們設定好文件類型var url = window.URL.createObjectURL(res.data);var filename = getFileName(res.headers);a.href = url;//HTML5中給a標簽增加了一個download屬性,只要有這個屬性,點擊這個鏈接時瀏覽器就不在打開鏈接指向的文件,而是改為下載a.download = filename;a.click();//URL.revokeObjectURL()靜態方法用來釋放一個之前通過調用 URL.createObjectURL() 創建的已經存在的 URL 對象。//當你結束使用某個 URL 對象時,應該通過調用這個方法來讓瀏覽器知道不再需要保持這個文件的引用了。window.URL.revokeObjectURL(url);
}
function filterResponse(res) {if (isDownload(res.headers)) {download(res);}
}
function errorResponse(err) {return Promise.reject(err);
}
httpLayer.interceptors.request.use(filterResponse, errorResponse);header中Content-Disposition的作用與使用方法:Content-disposition 是 MIME 協議的擴展,MIME 協議指示 MIME 用戶代理如何顯示附加的文件。Content-disposition其實可以控制用戶請求所得的內容存為一個文件的時候提供一個默認的文件名,文件直接在瀏覽器上顯示或者在訪問時彈出文件下載對話框。
格式說明:
content-disposition = "Content-Disposition" ":" disposition-type *( ";" disposition-parm )
字段說明:
Content-Disposition為屬性名
disposition-type是以什么方式下載,如attachment為以附件方式下載
disposition-parm為默認保存時的文件名
服務端向客戶端游覽器發送文件時,如果是瀏覽器支持的文件類型,一般會默認使用瀏覽器打開,比如txt、jpg等,會直接在瀏覽器中顯示,如果需要提示用戶保存,就要利用Content-Disposition進行一下處理,關鍵在于一定要加上attachment:
復制代碼 代碼如下:
Response.AppendHeader("Content-Disposition","attachment;filename=FileName.txt");
備注:這樣瀏覽器會提示保存還是打開,即使選擇打開,也會使用相關聯的程序比如記事本打開,而不是IE直接打開了。
Content-Disposition就是當用戶想把請求所得的內容存為一個文件的時候提供一個默認的文件名。具體的定義如下:
復制代碼 代碼如下:
content-disposition = "Content-Disposition" ":"disposition-type *( ";" disposition-parm )
disposition-type = "attachment" | disp-extension-token
disposition-parm = filename-parm | disp-extension-parm
filename-parm = "filename" "=" quoted-string
disp-extension-token = token
disp-extension-parm = token "=" ( token | quoted-string )
那么由上可知具體的例子:
Content-Disposition: attachment; filename="filename.xls"
當然filename參數可以包含路徑信息,但User-Agnet會忽略掉這些信息,只會把路徑信息的最后一部分做為文件名。
當你在響應類型為application/octet- stream情況下使用了這個頭信息的話,那就意味著你不想直接顯示內容,
而是彈出一個"文件下載"的對話框,接下來就是由你來決定"打開"還是"保存" 了。
注意事項:
1.當代碼里面使用Content-Disposition來確保瀏覽器彈出下載對話框的時候。 response.addHeader("Content-Disposition","attachment");一定要確保沒有做過關于禁止瀏覽器緩存的操作。如下:
復制代碼 代碼如下:response.setHeader("Pragma", "No-cache");
response.setHeader("Cache-Control", "No-cache");
response.setDateHeader("Expires", 0);

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/247528.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/247528.shtml
英文地址,請注明出處:http://en.pswp.cn/news/247528.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

V記錄2(文檔)Vue.extend構造器

1.簡單介紹 Vue.extend(options) 參數&#xff1a;對象 用法&#xff1a;使用Vue構造器&#xff0c;創建一個“子類”&#xff0c;參數是一個包含組件選項的對象&#xff0c;其中,data選項中必須是函數 描述&#xff1a;Vue.extend返回的是一個“擴展實例構造器”&#xff0c;也…

在javascript中,如何判斷一個被多次encode 的url 已經被decode到原來的格式?

% 而不能被無限次decodeURIComponent 可以用%來進行判斷 轉載于:https://www.cnblogs.com/zhouyideboke/p/11169705.html

推薦base.css

學習《編寫高質量代碼--Web前端開發修煉之道》 /* CSS Document */ /*css reset*/ body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,form,fieldset,input,textarea,p,blockquote,th,td{margin:0;padding:0;} table{ border-collapse:collapse;border-spacing:0;} fieldest,i…

如何通過RFID開發來迎接第四次工業革命(轉)

我們都經歷了革命性的沖擊&#xff0c;自上世紀90年代初的互聯網沖擊了文化和商業&#xff0c;但很少人知道如何完成RFID開發來迎接第四次工業革命&#xff0c;在接下來的二十年里&#xff0c;智能工廠的出現將成為一個重要組成部分。制造業作為我國工業的主體&#xff0c;面臨…

對js數組去重的研究

1.利用es5 let arr [1, 2, 3, 4, 5, 6, 7, 1, 2, 3] const uniquearr>{ return Array.from(new Set(arr)) } console.log(unique(arr))2.通過雙層循環使用splice刪除 let arr [1, 2, 3, 4, 5, 6, 7, 1, 2, 3] const uniquearr>{ // return Array.from(new Se…

一些前端開發經典書籍推薦和下載鏈接分享

下面的這些書都是我曾看過或了解過的&#xff1a; 一.HTML 1.《HTML5權威指南》 非常全面的書&#xff0c;內容也很新&#xff0c;包含了HTML5CSS3JS DOM。 下載鏈接&#xff1a;http://pan.baidu.com/s/1qYGn1qW HTML我暫時沒看什么書&#xff0c;學會了大部分的標簽后我…

RFID圖書管理系統程序源代碼(轉)

RFID圖書管理系統程序源代碼https://wenku.baidu.com/view/5f4e47f0c9d376eeaeaad1f34693daef5ef713d9.html

UOJ310 黎明前的巧克力 FWT

傳送門 我們要求的是\([x^0]\prod\limits_{i1}^n (2x^{a_i}1)\)&#xff0c;其中乘積定義為集合對稱差卷積。 這個直接做復雜度太高了&#xff0c;考慮優化。注意到在FWT之后&#xff0c;每一個序列中的值要么是\(3\)&#xff0c;要么是\(-1\)&#xff0c;而且這個只跟\(a_i\)有…

vue調用百度地圖API

安裝 $ npm install vue-baidu-map --save 全局注冊 在main.js 里面引入以下代碼 import BaiduMap from vue-baidu-mapVue.use(BaiduMap, {ak: 百度地圖密鑰AK }) 使用方法 <doc-preview><baidu-map class"map" style"display: flex; flex-direct…

mysql show processlist命令 詳解

SHOW PROCESSLIST顯示哪些線程正在運行。您也可以使用mysqladmin processlist語句得到此信息。如果您有SUPER權限&#xff0c;您可以看到所有線程。否則&#xff0c;您只能看到您自己的線程&#xff08;也就是&#xff0c;與您正在使用的MySQL賬戶相關的線程&#xff09;。請參…

JS 數據處理技巧及小算法匯總(轉載)

1、根據屬性來更新一個數組中的對象 const arr [ {id: 1, score: 1}, {id: 2, score: 2}, {id: 3, score: 4}]; //更新的值 const newValue {id: 3, score: 3} 更新數組中id為3的score值。 Es6 裝逼寫法如下&#xff1a; const result initial.map(x > x.id newValue.i…

讓行內元素(如圖片)在div中水平垂直居中 (干貨)

&#xff08;1&#xff09;第一種&#xff1a;用vertical-align <div class"method1"><span class"tiptop"></span><img class"test" src"img/Dota2.jpg" alt"dota2"> </div><style> …

對Canvas的研究

1。標簽定義圖形&#xff0c;比如圖表和其他圖像&#xff0c;您必須使用腳本來繪制圖形。 什么是 canvas? HTML5 <canvas> 元素用于圖形的繪制&#xff0c;通過腳本 (通常是JavaScript)來完成. <canvas> 標簽只是圖形容器&#xff0c;您必須使用腳本來繪制圖形。 …

Vue中watch的簡單應用

Vue.js 有一個方法 watch&#xff0c;它可以用來監測Vue實例上的數據變動。 如果對應一個對象&#xff0c;鍵是觀察表達式&#xff0c;值是對應回調&#xff0c;值也可以是方法名&#xff0c;或者是對象&#xff0c;包含選項。 下面寫兩個demo&#xff0c;參考demo來了解一下 …

小程序中textarea點擊按鈕事件

textarea 的 blur 事件會晚于頁面上的 tap 事件&#xff0c;如果需要在 button 的點擊事件獲取 textarea&#xff0c;可以使用 form 的 bindsubmit。 <view class"section"><form bindsubmit"bindFormSubmit"><textarea placeholder"f…

placeholder的兼容處理方法

placeholder是html5新增的一個屬性&#xff0c;極大的減輕了表單提示功能的實現&#xff0c;但是對于IE6-IE9真的是只能靠自己寫啦&#xff01; 但是在自己寫時會掉進了一個坑里&#xff0c;還好用了一會時間還是爬出來啦。 最終的解決方法方法如下&#xff1a; 1 <form nam…

常用數據處理

1、樹形數據轉換 在處理商品分類數據、企業列表數據等情況下&#xff0c;后臺會返回到前臺所有的數據。我們需要根據parentId,數據ID將數據轉換為樹形數據進行渲染。 /*** 樹形數據轉換* param {*} data* param {*} id* param {*} pid*/ export function treeDataTranslate(d…

運行Xcode時出現 Lazy loading NSBundle MobileCoreServices.framework和 Loaded MobileCoreServices.framework

運行Xcode時出現 Lazy loading NSBundle MobileCoreServices.framework和 Loaded MobileCoreServices.framework 解決方案&#xff1a; 1、打開項目的 Product-->Scheme --> Edit Scheme--> Run-->Arguments-->Environment Variables添加Name為OS_ACTIVITY_MO…

less中的for循環

.loop(count) when (counter > 0) { .loop((counter - 1)); // 遞歸調用自身width: (10px * counter); // 每次調用時產生的樣式代碼}轉載于:https://www.cnblogs.com/zhouyideboke/p/11178271.html

詳解 vue-cli 的打包配置文件代碼(轉)

一、前言 對于webpack基礎不好&#xff0c;node指令不通的童鞋。估計對自己搭建Vue、react腳手架是相當頭疼的&#xff0c;有種無從下手的感覺。然而&#xff0c;從頭看這2塊&#xff0c;耗時太長&#xff0c;而且說實話得練才行&#xff0c;不練練手看不明白。那大多數人就采取…