node上傳檔案到服務端
前言:
由於工作要求,需要寫個檔案上傳的介面。之前接觸的較少,都是使用現成的介面,自己寫介面時卻是遇到了難點。
該專案是在vue、koa基礎上搭建的,關於路由及其他相關知識,可檢視其他文章。
現將自己的理解寫下了,方便日後差異。如有不當地方,還請指正。
前端:
html
html結構可以寫的很簡單,一個input標籤就足夠。程式碼如下:
<input type="file" id="upload__input" @change="uploadFile" accept="" multiple>
js:
js主要處理input檔案變化後請求介面,並傳引數。
需要注意的是,引數不像表單那樣符合鍵值對的要求,需要使用formData的格式傳遞。程式碼如下:
uploadFile (e) { var fileValue = document.querySelector('#el-upload__input') this.srcOthers = fileValue.files[0]; var formData = new FormData(); formData.append('file', this.srcOthers); this.$http.post(this.rootUrl + "postsTxtFile/",formData) .then((data) => { console.log(data) }) .catch((err) => { console.log(err, 'error'); }); }
程式碼中核心是宣告formData變數,將input的files變數傳遞進去。可以模擬表單的形式形成鍵值對,用於非同步上傳二進位制檔案。
後端:
後端在拿到引數後,引數形式如下:
{ "method": "POST", "url": "/api/postsTxtFile/", "header": { "accept-language": "zh-CN,zh;q=0.9", "accept-encoding": "gzip, deflate, br", "referer": "http://localhost:8080/pageCompare", "content-type": "multipart/form-data; boundary=----WebKitFormBoundaryKdkJ1bBxZAeKZ1sS", "user-agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.26 Safari/537.36 Core/1.63.6726.400 QQBrowser/10.2.2265.400", "origin": "http://localhost:8080", "accept": "application/json, text/plain, */*", "content-length": "7140", "connection": "close", "host": "localhost:4000" } }
引數中並無法取到二進位制檔案的內容,因此需要將傳遞的引數解析為指定形式。在此,需要介紹使用中介軟體進行傳遞引數的解析。
因為傳遞的檔案型別為multipart/form-data型別,可使用connect-multiparty等中介軟體進行轉換,本專案中使用的是koa-body進行資料格式的轉換。
Koa-body
安裝
$ npm install koa-body
使用
如官網所示:
示例中index.js中引入koa之後,使用app.use的方式使用。如下:
const koa = require('koa');
const koaBody = require('koa-body');
// 中介軟體
app.use(koaBody({
jsonLimit: '20mb',
multipart: true
}));
程式碼中KoaBody函式傳遞了兩個引數,用於限制json的大小以及設定引數的型別為multipart型別。
另一種呼叫方式是在介面的router時使用,例如:
import Router from 'koa-router';
import koaBody from 'koa-body';
import postsTxtFile from '../application/postsTxtFile'
export default function () {
const router = Router();
router.prefix('/api');
router.post('/postsTxtFile/', koaBody(
{
jsonLimit: '20mb',
multipart: true
}
),
async (ctx) => {
// => POST body
ctx.body = await postsTxtFile(ctx.request);
// let para = ctx.request;
// let res = await postsTxtFile(para);
// ctx.body = res;
});
return router.routes();
}
程式碼中,在宣告postsTxtFile介面時,呼叫KoaBody函式,限制了json資料大小以及資料型別為multipart。而後呼叫postsTxtFile函式,返回處理後的資訊。
KoaBody處理後的請求files欄位格式如下:
"para": {
"file": {
"size": 287,
"path": "C:\\Users\\guojiangwei\\AppData\\Local\\Temp\\upload_30e4bc4b5cd52550160803d9f2f77904",
"name": "報告解讀靜態頁面.txt",
"type": "text/plain",
"mtime": "2018-11-27T07:57:56.510Z"
}
}
postsTxtFile.js
處理請求的介面函式的程式碼如下:
import fs from 'fs';
async function main(para) {
let res = {};
if (para && para.files) {
// res = {
// data: para.files.file.name
// }
// 獲得檔名
var filename = para.files.file.name;
// 複製檔案到指定路徑
var targetPath = 'src/uploadText/' + filename;
// 複製檔案流
fs.createReadStream(para.files.file.path).pipe(fs.createWriteStream(targetPath));
// 響應ajax請求,告訴它檔案上傳成功
res = { code: 200, data: { result: 'success' } };
return res;
} else {
return {
code: -1,
result: 'no files'
};
}
}
export default main;
程式碼中獲取了請求中的files的內容,並儲存到指定目錄中。
至此由前端上傳檔案到node後端儲存檔案的程式碼及流程基本完成。只是個人整理總結的內容,還請各位大佬指正。