基于nodejs的图片上传
- 后端插件 npm install multer
filesUtil.js 工具
javascript
const multer = require('multer');
const fs = require("fs");
const path = require('path');
// 上传文件
module.exports.uploadFiles = ({ dir = "./public/temp", key = "file", size = 10000 } = {}) => {
// 1. 对参数进行解构并设置默认值
// 2. 设置 multer 的参数,配置 diskStorage,来控制文件存储的位置以及文件名字等
const storage = multer.diskStorage({
// 2.1 确定图片存储的位置
destination: function (req, file, cb) {
// 当 dir 所对应目录不存在时,则自动创建该文件
try {
fs.accessSync(dir);
} catch (error) {
fs.mkdirSync(dir);
}
cb(null, dir);
},
// 2.2 确定图片存储时的名字。(注意:如果使用原名,可能会造成再次上传同一张图片的时候的冲突)
filename: function (req, file, cb) {
var changedName = new Date().getTime() + parseInt(Math.random() * 10) + path.extname(file.originalname);
cb(null, changedName);
}
});
// 3. 配置图片限制
const limits = {
// 限制文件大小
fileSize: 1024 * size,
// 限制文件数量
files: 10
};
// 4.生成的专门处理上传的一个工具,可以传入 storage、limits 等配置
const upload = multer({ storage, limits });
// 5. 返回多文件上传的设置信息(同样可用于单文件上传)
return upload.array(key);
}
// 移动文件
module.exports.moveFiles = ({ fromPath, toPath, filename } = {}) => {
if (!filename) {
console.log('========== 文件移动失败: filename 文件名不能为空 ==========');
return;
}
// 要移动的文件的原路径
const sourceFile = path.join(fromPath, filename);
// 判断源文件是否存在
try {
fs.accessSync(sourceFile);
} catch (error) {
console.log('========== 文件移动失败:' + sourceFile + ' 该文件不存在。==========');
return;
}
// 判断文件要移动的新路径是否存在,如果不存在,则创建
try {
fs.accessSync(toPath);
} catch (error) {
fs.mkdirSync(toPath);
}
// 文件移动后的新路径
const newFile = path.join(toPath, filename);
fs.renameSync(sourceFile, newFile);
return { newPath: newFile };
}FilesController.js
javascript
//写文件上传的逻辑以及返回
const { uploadFiles,moveFiles } = require('../utils/filesUtil')
const Utils = require('../utils/utils');
const UsersModel = require('../models/UsersModel');
class FilesController {
fileUp(req, res) {
const uploading = uploadFiles()
uploading(req, res, (err) => {
if (err) {
res.send({
code: 0,
msg: '文件上传失败'
})
} else {
//文件上传成功
//req.files就是文件上传成功后的一些相关的文件信息
console.log(req.files)
if (req.files.length > 0) {
res.send({
code: 1,
msg: '文件上传成功',
data: `/temp/${req.files[0].filename}`
})
} else {
res.send({
code: 0,
msg: '文件上传失败'
})
}
}
})
}
//后端修改用户信息的接口
async updateUserHeadImg(req, res) {
const bearerToken = req.get('Authorization')
console.log(bearerToken)
if (bearerToken) {
//解码token
const decode=Utils.verifyToken(bearerToken);
const {filename} = req.body
//
console.log(filename);
const fromPath='public/temp/'
const toPath='public/images/'
if (filename) {
//将图片移动到images文件夹下
try {
moveFiles({
fromPath,
toPath,
filename
})
// 修改用户信息
console.log(toPath+filename );
const data = await UsersModel.updateOne({ _id: decode._id }, { img:filename });
res.send({
code: 1,
msg: '修改成功',
})
} catch (error) {
res.send({
code: 0,
msg: '头像修改失败',
})
}
}
} else {
res.send({
code: 0,
msg: 'token失效'
})
}
}
}
module.exports = new FilesController();- 前端利用 文件框以及FormData 构造函数对文件数据进行格式转换,转换成二进制流,以及ajax向后端发数据
javascript
const flag = true;
// 确认修改
$("#changeImg").on('click', async function (e) {
if (flag) {
confirm("请先选择头像");
return;
}
let filename = $("#headImg").css("background-image");
filename = filename.substring(filename.lastIndexOf("/") + 1);
filename = filename.replace(`")`, "");
let option = {
url: "/files/updateUserHeadImg",
data: {
filename
}
}
const res = await $cn(option);
console.log(res);
return
});
// 发送文件数据
$("#fileImg").on('change', async function (e) {
flag = false;
// console.dir(this.files[0]);
// 1.拿文件数据
const fileInfo = this.files[0]
// 2.通 FormData 构造函数对文件数据进行格式转换,转换成二进制流
const fd = new FormData();
fd.append('file', fileInfo);
const res = await $upFile(fd);
$("#headImg").css("background-image", `url(${res})`);
});ajax
javascript
// 默认异步 jquery Promise
export function $cn({ url, method="post", data, async = true, dataType = "json", timeout = 3000 } = {}) {
url = URL_NODE_SERVER + url;
const token=getLocal("token");
data=JSON.stringify(data); // contentType:"application/json"的时候必须串json字符串
const exclude= /\/login|\/register/;
if (token==""&&!exclude.test(url)) {
return {code:-901,msg:"没有token"};
}
return new Promise((resolve,reject) => {
$.ajax({
type: method,url: url,data,dataType,async,timeout, // 超时设置 单位毫秒
contentType:"application/json", //"application/json"
headers:{
//将token每次请求的时候放在请求头中,然后需要在token之前拼接'Bearer '
Authorization:'Bearer ' + token
},
success:(res)=>{
if (res.data) {
if( res.data.img){
res.data.img=URL_NODE_SERVER+ res.data.img;
}
}
resolve(res);
},
error:(res)=>{
reject(res);
},
});
})
}
// 用于文件传输 头像
export function $upFile(data) {
const url = URL_NODE_SERVER + '/files/fileUp';
const token=getLocal("token");
const exclude= /\/login|\/register/;
if (token==""&&!exclude.test(url)) {
return {code:-901,msg:"没有token"};
}
return new Promise((resolve,reject) => {
$.ajax({
type: "post",url: url,data, // 超时设置 单位毫秒
//禁止jqueryAjax对传输的数据格式进行内部处理
contentType:false,
processData:false,
headers:{
//将token每次请求的时候放在请求头中,然后需要在token之前拼接'Bearer '
Authorization:'Bearer ' + token
},
success:(res)=>{
resolve(URL_NODE_SERVER+res.data);
},
error:(res)=>{
reject(res);
},
});
})
}