需求描述
- 允許用戶上傳文件,服務端從請求中讀取并且解析
- 允許用戶下載文件,如報表導出功能,基于當前展示的表格數(shù)據(jù),導出excel文件
涉及到的技術(shù)點
- 文件讀寫
- 文件上傳
- 文件下載
文件上傳與讀取文件
前端代碼
比較常見的場景是:在前端頁面中會有一個表單,表單中會輸入一些字段,同時上傳文件。
代碼示例:
<form method="POST" action="/apps/rel" encType="multipart/form-data" name="form">
<input id="inputFile" type="file"
accept="application/vnd.ms-excel|xls"
name="inputFile" onChange={this.handleFileChange}/>
<button onClick={this.handleSubmit}>點擊提交</button>
</form>
表單提交一般通過js代碼提交:首先做數(shù)據(jù)合法性校驗,然后執(zhí)行form.submit()執(zhí)行提交。如果不想頁面跳轉(zhuǎn),則將表單target設置為一個隱藏的iframe。
服務端代碼
服務端處理上傳文件使用multer npm包。
代碼示例:
//先引入multer
var multer = require('multer');
var upload = multer();
//從upload中獲取文件
router.post('/rel', upload.fields([{name: 'inputFile', maxCount: 1}]),function(req,res,next){
var inputFiles = req.files; //未傳時為undefined
...
//讀取文件內(nèi)容
var content = inputFiles['inputFile'][0].buffer.toString();
})
multer的更多使用請參考官方文檔。
文件下載
文件下載比較典型的例子是報表導出:通過數(shù)據(jù)庫數(shù)據(jù)查詢,寫入到csv文件中,然后支持瀏覽器下載。
代碼示例:
router.get('/export',(req,res,next)=>{
//查詢數(shù)據(jù)庫
...
let realPath = path.join(TMP_PATH, fileName);
let writeStream = fs.createWriteStream(realPath);
let bom = new Buffer('\xEF\xBB\xBF', 'binary');
writeStream.write(bom);
//寫入數(shù)據(jù)內(nèi)容
...
writeStream.end();
writeStream.on('finish', ()=> {
res.download(realPath, outName, (err)=> {
fs.unlink(realPath, (err2)=> {
if (err2) {
logger.error('刪除文件失敗,err=' + err);
}
});
if (err) {
logger.error(err);
res.status(404).end();
}
});
});
})
常見問題
- 寫入csv中文亂碼問題
由于 NodeJS只支持 ascii、utf8、base64、binary 編碼方式, 不支持 MS 的 utf-8 + BOM 格式, 所以 excel 打開中文亂碼。
解決方法:既然excel需要BOM,寫入數(shù)據(jù)前先加入一個BOM。utf-8對應的BOM是EF BB BF
let writeStream = fs.createWriteStream(realPath);
let bom = new Buffer('\xEF\xBB\xBF', 'binary');
writeStream.write(bom);
writeStream.write('hello');
writeStream.write('繼續(xù)測試');
writeStream.end('中文');
...