在
eggjs
中上傳文件的官方文檔html
一、配置上傳的路由git
module.exports = (app) => {
const { router, controller } = app;
router.resources('file', '/api/v1/file', controller.file);
};
複製代碼
二、在config/config.default.js
中配置上傳的基本配置(能夠參考官方文檔)github
...
// 配置上傳
config.multipart = {
fileSize: '50mb',
mode: 'stream',
fileExtensions: ['.xls', '.txt'], // 擴展幾種上傳的文件格式
};
...
複製代碼
三、安裝幾個基本的包ajax
npm install await-stream-ready stream-wormhole dayjs
複製代碼
form
表單上傳一、模板的代碼shell
<form method="POST" action="/api/v1/file" enctype="multipart/form-data">
title: <input name="title" /> file: <input name="file" type="file" />
<button type="submit">Upload</button>
</form>
複製代碼
fs
及數據流寫入文件(在控制器層)async create() {
// 獲取文件流
const stream = await this.ctx.getFileStream();
// 定義文件名
const filename = Date.now() + path.extname(stream.filename).toLocaleLowerCase();
// 目標文件
const target = path.join('app/public/uploads', filename);
//
const writeStream = fs.createWriteStream(target);
console.log('-----------獲取表單中其它數據 start--------------');
console.log(stream.fields);
console.log('-----------獲取表單中其它數據 end--------------');
try {
//異步把文件流 寫入
await awaitWriteStream(stream.pipe(writeStream));
} catch (err) {
//若是出現錯誤,關閉管道
await sendToWormhole(stream);
// 自定義方法
this.error(err);
}
// 自定義方法
this.success({ url: '/public/uploads/' + filename });
}
複製代碼
url
地址傳遞服務層,存到數據庫中ajax
上傳文件一、基本的html
頁面數據庫
<h1>ajax提交</h1>
<input type="text" id="username" />
<input name="file" type="file" id="file" />
<button id="btn">提交</button>
複製代碼
二、jq
的ajax
npm
<script>
$('#btn').on('click', function() {
console.log('提交按鈕');
let formData = new FormData();
formData.append('title', $('#username').val());
formData.append('image', $('#file')[0].files[0]);
console.log(formData);
$.ajax({
url: '/api/v1/file',
data: formData,
method: 'post',
contentType: false,
processData: false,
success: function(result) {
console.log(result);
},
});
});
</script>
複製代碼
一、修改上傳代碼的控制器api
const fs = require('fs');
const path = require('path');
//故名思意 異步二進制 寫入流
const awaitWriteStream = require('await-stream-ready').write;
//管道讀入一個蟲洞。
const sendToWormhole = require('stream-wormhole');
const dayjs = require('dayjs');
async create() {
const stream = await this.ctx.getFileStream();
console.log('-----------獲取數據 start--------------');
console.log(stream.fields);
console.log('-----------獲取數據 end--------------');
// 基礎的目錄
const uplaodBasePath = 'app/public/uploads';
// 生成文件名
const filename = `${Date.now()}${Number.parseInt( Math.random() * 1000, )}${path.extname(stream.filename).toLocaleLowerCase()}`;
// 生成文件夾
const dirname = dayjs(Date.now()).format('YYYY/MM/DD');
function mkdirsSync(dirname) {
if (fs.existsSync(dirname)) {
return true;
} else {
if (mkdirsSync(path.dirname(dirname))) {
fs.mkdirSync(dirname);
return true;
}
}
}
mkdirsSync(path.join(uplaodBasePath, dirname));
// 生成寫入路徑
const target = path.join(uplaodBasePath, dirname, filename);
// 寫入流
const writeStream = fs.createWriteStream(target);
try {
//異步把文件流 寫入
await awaitWriteStream(stream.pipe(writeStream));
} catch (err) {
//若是出現錯誤,關閉管道
await sendToWormhole(stream);
this.error();
}
this.success({ url: path.join('/public/uploads', dirname, filename) });
}
複製代碼
二、其它的都不變app
三、上傳生成的目錄dom
2019
└── 06
└── 21
├── 1561097630832563.png
└── 1561097675536863.jpeg
複製代碼
一、在基類的控制器中
const { Controller } = require('egg');
const fs = require('fs');
const path = require('path');
//故名思意 異步二進制 寫入流
const awaitWriteStream = require('await-stream-ready').write;
//管道讀入一個蟲洞。
const sendToWormhole = require('stream-wormhole');
const dayjs = require('dayjs');
class BaseController extends Controller {
// 上傳文件的通用方法
async uploadFile(category = '') {
const stream = await this.ctx.getFileStream();
// 基礎的目錄
const uplaodBasePath = 'app/public/uploads';
// 生成文件名
const filename = `${Date.now()}${Number.parseInt( Math.random() * 1000, )}${path.extname(stream.filename).toLocaleLowerCase()}`;
// 生成文件夾
const dirname = dayjs(Date.now()).format('YYYY/MM/DD');
function mkdirsSync(dirname) {
if (fs.existsSync(dirname)) {
return true;
} else {
if (mkdirsSync(path.dirname(dirname))) {
fs.mkdirSync(dirname);
return true;
}
}
}
mkdirsSync(path.join(uplaodBasePath, category, dirname));
// 生成寫入路徑
const target = path.join(uplaodBasePath, category, dirname, filename);
// 寫入流
const writeStream = fs.createWriteStream(target);
try {
//異步把文件流 寫入
await awaitWriteStream(stream.pipe(writeStream));
} catch (err) {
//若是出現錯誤,關閉管道
await sendToWormhole(stream);
return {
error: '錯誤',
};
}
return {
url: path.join('/public/uploads', category, dirname, filename),
fields: stream.fields,
};
}
}
module.exports = BaseController;
複製代碼
二、在上傳文件的控制器中使用
const Controller = require('./../core/base_controller');
class FileController extends Controller {
async create() {
// 上傳頭像的,會在uploads文件夾下有個avatar的文件夾下面纔是201九、0六、21
const { url, fields } = await this.uploadFile('avatar');
const result = await 服務層;
this.success(url);
}
}
複製代碼