需求
博客系统翻新,需要上传图片的功能,本来想着一起把上传文件做上的,但是目前没太大用处,所以先做一个上传图片。
开发
前端
前端主要是通过 <input type='file' /> 调起图片选择,将选中的图片以 formdata 的方式发送出去。
javascript
export function uploadImage(imageFormData, callback) {
return request({
url: '/upload',
method: 'post',
data: imageFormData,
headers: {
'Content-Type': 'multipart/form-data',
'X-Requested-With': 'XMLHttpRequest'
},
onUploadProgress(progressEvent) {
if (callback) {
callback(progressEvent)
}
}
})
}
server
Node.js 中自带了文件操作的 API,虽然早期非常难用,但是 Node v10 版本以后的还可以。
重点使用的是 fs.promise 的一系列 API。
将文件直接保存到 app/public 下,页面端可以通过反向代理后台接口 127.0.0.1:7002/public 直接获取到文件。
javascript
async upload() {
const {ctx, app} = this;
const fileData = ctx.request.files[0];
// 获取当前日期
const activeDate = ctx.helper.getNowDate();
const uploadFilePath = path.join(__dirname, '../public/' + activeDate + '/');
const file = await fsPromises.readFile(fileData.filepath);
// 创建日期文件夹
if (!fs.existsSync(uploadFilePath)) {
await fsPromises.mkdir(uploadFilePath, {recursive: false});
}
// 生成服务端文件名
const newFileName = ctx.helper.snowflakeId() + '.' + ctx.helper.getFileSuffix(fileData.filename);
const serverFilePath = uploadFilePath + newFileName;
// 保存文件
await fsPromises.writeFile(serverFilePath, file);
ctx.status = 200;
ctx.body = {
code: 200,
success: true,
data: {
name: fileData.filename,
url: 'http://' + ctx.host + '/public/' + activeDate + '/' + newFileName,
},
msg: '上传成功',
show: true
}
}
总结
上传图片的整个过程还是比较顺利的,但是需要注意的是,这里上传文件没有加上中途校验,存在一定的安全风险和隐患。
为了便于文件查阅,加上了按照日期分文件夹存储。
另外对于大文件的上传这里也并没有涉及,断点续传等高阶的内容也没有添加,仅仅是最基础的上传操作。