摘要:不過這種方式有問題,目前查到的大部分過程都是會在服務(wù)器新建出一個文件,等下載完畢在做刪除,還沒有找到可以跨過這一步的方式。
Content-Disposition / Content-Type Content-Disposition
http 頭部的 Content-Disposition字段,規(guī)定了返回的內(nèi)容用什么形式展示
value | 含義 | 是否默認(rèn) |
---|---|---|
inline | 以網(wǎng)頁或者頁面的一部分 | 是 |
attachment | 以附件的形式下載并保存到本地 | 否 |
http.createServer((req, res) => { res.setHeader("Content-Disposition", "attachment") res.end("123 - 321 - 1234567") })
前端需要使用window.open 形式訪問 此路由就可以實現(xiàn)文件的下載
window.open(xxxx)
或者使用 H5新屬性 a 標(biāo)簽
點擊下載Content-Type
http.createServer((req, res) => { res.setHeader("Content-Type", "application/octet-stream") res.end("123 - 321 - 1234567") })
同上前端使用 open 或者 a標(biāo)簽進行處理
備注: 如果使用普通的請求,是不可以的,比如使用ajax
window.openwindow.open 可以下載文件的原因是,瀏覽器遇到無法解析的文件就是執(zhí)行下載
當(dāng)使用瀏覽器打開文件時, 如果它無法解析,那么就會把該文件下載下來
http.createServer((req, res) => { const data = fs.readFileSync("./Zip.zip") res.end(data) })
拿到的data是一個buffer 對象,那么直接寫一個Buffer可以實現(xiàn)下載么
data = new Buffer("我是誰,誰是我")
嘗試后發(fā)現(xiàn),koa是可以的。但是原生直接這么寫是不行的
http.createServer((req, res) => { const newBuf = new Buffer("我是誰,誰是我") res.end(newBuf) })通過接口拿到數(shù)據(jù)之后進行下載
在實際項目中,文件下載可能出現(xiàn)的場景
對于已經(jīng)在服務(wù)器存在的文件進行下載,比如圖片資源
將一些查詢數(shù)據(jù)導(dǎo)出到本地, 比如mysql查詢結(jié)果導(dǎo)出csv
對于已存在的資源,可以直接使用 上面說的 winodw.open 或者 a 標(biāo)簽進行下載,那么對于不是以文件形式存在的資源呢
data URI經(jīng)常見到使用 data URI scheme 的是圖片, 一般為了減少http請求,會將圖片直接以base64的形式展示在html中
也可以應(yīng)用到文件下載中
router.get("/download", async (ctx, next) => { const newBUf = new Buffer("我是誰,誰是我") ctx.body = newBUf }
axios.get(`${path}`) .then(function ({data}) { let a = document.createElement("a"); a.href = "data:text/plain;charset=utf-8," + data; a.download = "myfilename.png"; a.click(); // 記得處理臨時元素 防止內(nèi)存泄漏 a = null })Blob
Blob 是表示一個類文件對象,可以用它來表示一個文件
server 部分
http.createServer((req, res) => { res.setHeader("Access-Control-Allow-Origin", "*"); let end = "" if (req.url.includes("/down")) { const newBUf = new Buffer("我是誰,誰是我") end = newBUf } res.end(end) }
前端
const xhr = new XMLHttpRequest(); xhr.open("GET", path); xhr.responseType = "blob"; xhr.onload = function () { const blob = xhr.response; const url = URL.createObjectURL(blob); // 通過a標(biāo)簽去下載 const link = document.createElement("a"); link.href = url; link.download = fileName; link.click(); link = null URL.revokeObjectURL(url); }; xhr.send();
嘗試用 window.open 方式,發(fā)現(xiàn)不可以
目前常用的各個第三方庫也支持返回內(nèi)容為blob格式
axios.get(`${path}`, { responseType: "blob" })
或者 fetch
fetch(path).then(res => res.blob().then(blob =>{ ... })window.URL
createObjectURL
用 blob 對象來創(chuàng)建一個 object URL(它是一個 DOMString),我們可以用這個 object URL 來表示某個 blob 對象,這個 object URL 可以用在 a 標(biāo)簽的 href屬性上,然后觸發(fā)點擊事件,就可以下載文件了
revokeObjectURL
為了避免避免內(nèi)存泄漏,需要手動釋放創(chuàng)建的 object URL
缺點構(gòu)建完 blob 對象后才會轉(zhuǎn)換成文件
從代碼就能看出,需要先將返回內(nèi)容轉(zhuǎn)為blob才進行下載操作,如果用戶操作的是一個很大的資源,在等待文件正式下載前,還需要一段時間等待格式的轉(zhuǎn)化
實例 將mysql數(shù)據(jù) 導(dǎo)出 csv這邊直接用數(shù)據(jù)模擬mysql查詢結(jié)果, 在網(wǎng)上查到兩種拼接方式,肯定有其余的方案
第一種
const result = [ ["id", "oreder", "name", "status" ], [1, "201904120201", "正在加載", "已完成"], [18, "201904120204", "測試189", "待付款"], [22, "201904120209", "藍(lán)田日暖", "待付款"], ] // 可以看到 result 數(shù)組的第一組是 csv的各個字段標(biāo)題 const data = csvData.reduce((cur, next) => `${cur + next.join(",")} `, "") const blob = new Blob([data]); const url = URL.createObjectURL(blob); let a = document.createElement("a"); a.href = url; a.download = filename; a.click(); a = null window.URL.revokeObjectURL(url);
第二種
const result = [ [1, "201904120201", "正在加載", "已完成"], [18, "201904120204", "測試189", "待付款"], [22, "201904120209", "藍(lán)田日暖", "待付款"], ] // result 就是正常的數(shù)據(jù)格式 // 解決亂碼問題 let dataType = "uFEFF" // 添加表格的頭子段 dataType += ([" 訂單編號", "用戶", "動態(tài)ID"].join(",")) dataType += " " csvData.forEach(item => { dataType += ([item.id, item.order, item.name, item.staus].join(",")) dataType += " " }) const blob = new Blob([dataType], {type: "text/csv"})如果有幾段流文件,前端需要下載拼接成一個完整文件,如何實現(xiàn)
肯定是在 server端進行文件的拼接操作,然后返回到前端下載
大致過程
const content1 = "這里是第1段文件內(nèi)容" const content2 = "這里是第2段文件內(nèi)容" ctx.body = { code:200, data: content1 + content2 }
前端就是上文中的blob 下載方式了
批量下載如何處理其實這個問題是在查詢資料的過程有人提到的問題
window.open
批量寫了多個 window.open 在Chrome中 可以正常使用,但是在safari中,只能打開一個窗口,下載一個文件
轉(zhuǎn)為下載一個zip 文件
感覺如果將所有文件合并成為一個xxx.zip 然后對 這個zip文件做下載。不過這種方式有問題,目前查到的大部分過程都是會在服務(wù)器新建出一個 zip 文件,等下載完畢在做刪除,還沒有找到可以跨過這一步的方式。
參考文章Data URI Scheme
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/103491.html
摘要:解決方法如果使用頁面數(shù)據(jù)不超過一屏禁止?jié)L動,那么即使變成了頁面也不會有什么變化。 作者:@micky思 @wupq @yewq 在H5的開發(fā)中,個人的制作頁面布局習(xí)性不同,多多少少會產(chǎn)生在真機上input的光標(biāo)和鍵盤的彈出會出現(xiàn)的各種BUG,文中整理了部分遇到的問題,歡迎新增 ios移動端輸入框上浮導(dǎo)致輸入位置偏移 問題原因:遮罩層定位為fixed,當(dāng)鍵盤彈起時,ios11以及以下...
摘要:解決方法如果使用頁面數(shù)據(jù)不超過一屏禁止?jié)L動,那么即使變成了頁面也不會有什么變化。 作者:@micky思 @wupq @yewq 在H5的開發(fā)中,個人的制作頁面布局習(xí)性不同,多多少少會產(chǎn)生在真機上input的光標(biāo)和鍵盤的彈出會出現(xiàn)的各種BUG,文中整理了部分遇到的問題,歡迎新增 ios移動端輸入框上浮導(dǎo)致輸入位置偏移 問題原因:遮罩層定位為fixed,當(dāng)鍵盤彈起時,ios11以及以下...
摘要:解決方法如果使用頁面數(shù)據(jù)不超過一屏禁止?jié)L動,那么即使變成了頁面也不會有什么變化。 作者:@micky思 @wupq @yewq 在H5的開發(fā)中,個人的制作頁面布局習(xí)性不同,多多少少會產(chǎn)生在真機上input的光標(biāo)和鍵盤的彈出會出現(xiàn)的各種BUG,文中整理了部分遇到的問題,歡迎新增 ios移動端輸入框上浮導(dǎo)致輸入位置偏移 問題原因:遮罩層定位為fixed,當(dāng)鍵盤彈起時,ios11以及以下...
摘要:函數(shù)防抖場景假設(shè)網(wǎng)站有個搜索框用戶輸入文本我們會自動聯(lián)想匹配出一些結(jié)果供用戶選擇我們可能首先想到的做法就是監(jiān)聽事件然后異步查詢結(jié)果但是如果用戶快速的輸入了一串字符假設(shè)是個字符那么就會在瞬間觸發(fā)次請求這無疑不是我們想要的我們想要的是用戶停止輸 函數(shù)防抖 場景 假設(shè)網(wǎng)站有個搜索框, 用戶輸入文本我們會自動聯(lián)想匹配出一些結(jié)果供用戶選擇,我們可能首先想到的做法就是監(jiān)聽keypress事件, 然...
摘要:一直使用定義變量,的出現(xiàn)給變量定義增加了兩個大將,。聲明的變量,塊作用域,不重復(fù)聲明覆蓋,限制了變量的作用域,保證變量不會去污染全局變量,所以盡量將改為用。 一直使用var定義變量,ES6的出現(xiàn)給變量定義增加了兩個大將let,const。那它們有什么區(qū)別呢。 1、const關(guān)鍵字它的作用就是定義一個常量,一旦定義無法更改,不能重復(fù)聲明覆蓋; showImg(https://segmen...
閱讀 2908·2021-11-17 09:33
閱讀 1629·2021-10-12 10:13
閱讀 2424·2021-09-22 15:48
閱讀 2311·2019-08-29 17:19
閱讀 2587·2019-08-26 11:50
閱讀 1564·2019-08-26 10:37
閱讀 1732·2019-08-23 16:54
閱讀 2916·2019-08-23 14:14