express下載excel

update

  • 靠,不用轉stream的,res.send()能直接發buffer的… …

  • 用node寫了個查詢數據生成和下載excel的功能,踩了些坑,記一下
  • 先貼個例子
app.get('/download', function (req, res, next) {
  let data = [[1, 2, 3], [true, false, null, 'sheetjs'], ['foo', 'bar', new Date('2014-02-19T14:30Z'), '0.3'], ['baz', null, 'qux']];
  let range = {s: {c: 0, r:0 }, e: {c:0, r:3}}; // A1:A4
  let option = {'!merges': [ range ]};

  let buffer = xlsx.build([{name: "mySheetName", data: data}], option);
  
  let filename = '測試編碼.xlsx';
  filename = urlencode(filename);

  res.set({
    'Content-Type': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
    'Content-Disposition': `filename=${filename}`,
    'Content-Length': buffer.length
  });
	res.send(buffer,'binary');
	//不用轉stream
	//let bufferStream = new stream.PassThrough();
	//bufferStream.end(buffer);
	//  bufferStream.pipe(res);
});

問題:不想讀寫文件

  • 我是用node-xlsx這個包來生成excel的,本來想着生成一個文件再用express自帶的res.download()直接下的,結果node-xlsx直接返回了一個buffer,這就得重新考慮一下了。
  • 最容易想到的下載方式是,把這個buffer寫到一個臨時文件夾裏,再進行下載。但是轉念一想不對啊,我本來就在內存裏生成的,幹嘛要寫到文件裏再讀出來呢?

方法:buffer轉成stream輸出

  • 再看看express自帶的方法res.download()是怎麼做的,它是對res.sendFile()的一個封裝,需要讀取文件的路徑。但下載文件並不止這一種方法,還可以使用的方式進行傳輸,將buffer轉成stream直接輸出到響應當中就不需要經過文件的中轉了。
  • 接着我就在node的文檔裏看到這個函數:fs.createReadStream(path[, options]),path的簽名長這樣path <string> | <Buffer> | <URL>,把這個buffer傳進去產生stream,再stream.pipe(res)問題不就解決了?事實證明我還是圖樣。。。
  • 可能是我對這個函數的理解出了一些偏差,createReadStream這個函數把buffer傳進去直接就報錯了,它只要字符串格式的參數。那就換一種把buffer轉stream的寫法唄
    let bufferStream = new stream.PassThrough();
    bufferStream.end(buffer);
    bufferStream.pipe(res);
    
  • 這次運行倒是沒問題,問題是下載下來的的文件居然是個download.zip,這是個什麼鬼?還解壓出來一堆xml。。。
  • 等等,我目前還沒有設置過文件名和擴展名吧,那瀏覽器要怎麼識別出來這是個什麼文件呢?難怪會出問題。對於如何解決,這有一份現成的參考,res.download()不就能好好的傳文件過來了?

設置http響應頭

  • 拿個文件試了一下res.download(),發現它在http響應的headers裏設置了Content-TypeContent-Disposition用以描述文件的類型和名稱,我也依樣畫葫蘆設置了這幾個屬性,總算是能正常下載了。
  • 還得注意一點,http header 裏面是不支持中文編碼的,要用urlencode把中文轉成%E6%B5%8B這樣的字符串才能用

http 響應頭

  • Content-Type 指定http協議中的媒體類型(MIME)
    • 常見的有html:text/html 、文本:text/plain之類的。xlsx格式的excel對應的是application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
  • Content-Disposition 指示響應的內容該以怎樣的形式展示
    • attachment : 表明是否是附件,帶上它就會彈出下載對話框。雖然excel不用這個也是彈出對話框,但是對那些瀏覽器可以直接打開的文件,比如html,jpg之類的來說,帶上這個參數彈出下載框,不帶就直接在瀏覽器上顯示了
    • filename : 文件名
    • filename* :也是文件名,這是考慮到兼容性 (IE) 的寫法。如果二者同時存在且瀏覽器支持的話,會優先採用 filename*。res.download 就是兩個一起寫的
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章