前端下載普通文件與二進制流文件

前端下載文件一般會遇到這樣兩種狀況html

  1. 文件上傳到資源服務器上,後端只保存了文件地址,前端拿到後端返回的文件地址直接下載。
  2. 文件就存在後端服務器上(一般是臨時根據前端參數動態生成,用完就刪除),後端讀取文件後向前端返回文件的二進制流。

下面如下載excel文件爲例,分別模擬展現這兩種狀況。(前置準備:vscode,node8+,vue-cli3.5+)。前端

1、 經過文件地址直接下載vue

在空目錄test下新建service目錄模擬後端,新建index.html文件模擬前端。node

在service目錄中新建一個excel文件 test.xlsx用於下載。ios

安裝serve用來啓動靜態資源服務器ajax

npm install -g serve
複製代碼

進入service目錄,啓動服務vue-cli

cd service 
serve -s
複製代碼

此時這個test文件的地址就是:http://localhost:5000/test.xlsxnpm

在頁面中放一個a標籤,href中寫上文件的路徑,並寫上download屬性。axios

<a href="http://localhost:5000/test.xlsx" download>點擊下載</a>
複製代碼

在瀏覽器中打開index.html,點擊下載。後端

這種下載至關於一個get請求,瀏覽器直接訪問該靜態資源地址,download屬性告訴瀏覽器這個a標籤不是打開頁面預覽而是進行下載。

這與一般在實際項目中經過ajax請求接口無關,只須要照常請求,由於後端返回的只是文件的地址,拿到地址後綁定在a標籤中或者經過window.open()均可以進行下載,再也不單獨在項目中進行演示。

2、二進制流文件下載

這種狀況通常就是實際項目使用的ajax請求接口方式,好比post請求,前端傳遞若干參數,後端返回文件二進制流。

刪除index.html,返回test目錄下,使用vue-cli建立一個vue項目。

cd ../
vue create demo 
複製代碼

選擇最簡單的default模板,建立好後進入項目目錄安裝axios,最後啓動。

cd demo
npm i axios --save
npm run serve
複製代碼

刪除src/App.vue中的多餘內容,添加一個下載按鈕。

<input type="button" value="點擊下載">
複製代碼

在service目錄中建立service.js寫一個下載的接口。

關於跨域cors設置參考:juejin.cn/post/684490…

const http = require("http");
const fs = require("fs");

// 建立服務
const server = http.createServer((req,res) => {  
  // 下載接口  
  if(req.url === "/download") {    
    res.writeHead(200, {      
      "Content-type": "application/vnd.ms-excel", // 返回excel文件            
      // 跨域設置      
      "Access-Control-Allow-Origin": "*",      
      "Access-Control-Allow-Headers": "content-type"    
    })

    // 異步讀取文件內容    
    fs.readFile("test.xlsx", (err, data) => {       
      // 返回二進制流文件        
      res.end(data)    
    })  
  }
})

// 服務啓動在3000端口
server.listen(3000)
console.log("server run at 3000")
複製代碼

在service目錄下新開一個終端窗口,啓動後端服務。

node service.js
複製代碼

回到App.vue,給下載按鈕添加點擊事件。

<input type="button" value="點擊下載" @click="handleDownload">

handleDownload() {  
  axios({    
    method: 'post',    
    url: "http://localhost:3000/download",    
    data: {      
      test: "test data"    
    } 
  }).then(response => {      
      console.log(response.data)  
   })
},
複製代碼

此時點擊下載,能夠看到返回的結果是亂碼。

其實根本原理跟上面普通下載同樣,都是經過一個文件的地址去下載,因此如今關鍵就是如今把這些二進制數據生成一個文件url。

首先設置axios配置項返回結果爲二進制格式。

axios({  
  method: 'post',  
  url: "http://localhost:3000/download",  
  data: {    
    test: "test data"  
  },  
  responseType: "arraybuffer" // arraybuffer是js中提供處理二進制的接口
})
複製代碼

拿到返回數據後,將二進制數據生成一個文件url,用URL.createObjectURL生成url時須要傳入Blob類型的參數。

關於Blob類型:juejin.cn/post/684490…

生成了url後就是模擬a標籤來下載。

.then(response => {          
  // 用返回二進制數據建立一個Blob實例          
  let blob = new Blob([response.data], {            
    type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", 
  }) // for .xlsx files          

  // 經過URL.createObjectURL生成文件路徑          
  let url = window.URL.createObjectURL(blob)          

  // 建立a標籤          
  let ele = document.createElement("a")          
  ele.style.display = 'none'          

  // 設置href屬性爲文件路徑,download屬性能夠設置文件名稱          
  ele.href = url          
  ele.download = "測試文件"          

  // 將a標籤添加到頁面並模擬點擊          
  document.querySelectorAll("body")[0].appendChild(ele)          
  ele.click()          

  // 移除a標籤          
  ele.remove()        
});
複製代碼

回到瀏覽器點擊下載,此次二進制流文件下載成功。

相關文章
相關標籤/搜索