在上传文件时,有时候会遇到想要多种类型图片的区分上传
例:在做商品管理上传时,想在提交时,上传缩略图一类,详细信息图一类,而这两块在提交的时候,如果不区分开的话,提交时会全部发到后台,而不能产生区分(功能点是在后端对前端页面提供一个http地址直接通过地址访问图片,而缩略图所在的部分和详细图所在的部分是分开存储的,所以要区分上传)
实现方法:
前端:
①在图片的上传时就需要区分,在react中就在state中分开独立创建数组去存储想要上传的图片,vue则是在data中分开创建数组
let data = JSON.parse(JSON.stringify(this.state.addInfo));
data['price'] = Number(data.price);
data['marketPrice'] = Number(data.marketPrice);
data['stock'] = Number(data.stock);
// message.success('添加成功');
handleAddGoods({
imgfiles: this.state.thumbnailList,
files: this.state.fileList,
addInfo: data,
}).then(response => {
console.log(response);
setTimeout(() => {
this.setState({
loading: false,
});
message.success('添加成功');
setTimeout(()=>{
this.props.history.replace('/goods')
},1000)
}, 2000);
});
②点击上传后(触发上传的事件),上传事件中要使用fromData去处理图片文件,具体就是用formData.append(‘名’,json字符串或文件),记住,由于是要区分开的,所以就必须要append多次,然后名字取不同的名字,处理好所有要发送到后端的东西后,就可以发送请求了,记得在请求头中加上’Content-type’: ‘multipart/form-data’
const handleAddGoods = data => {
let formData = new FormData();
formData.append('info', JSON.stringify(data.addInfo));
data.imgfiles.forEach((value, index) => {
formData.append('imgfile', value.originFileObj);
});
data.files.forEach((value, index) => {
formData.append('file', value.originFileObj);
});
console.log(data);
return axios.post('http://localhost:8080/addGoodsInfos', formData, {
'Content-type': 'multipart/form-data',
});
};
后端:(这里写的是nodejs的后端)
由于使用的是nodejs,所以使用时要把upload引入
const multer = require("multer");
const upload = multer({
dest: "./uploads"
});
①使用中间件去处理传过来的文件,由于是多文件上传,所以要使用upload.fields
(.single是单文件上传,.array是多个文件上传(不使用这个的原因是为了区分,只能接收一个数组,数组中是多个文件),.fields也是多文件上传,但是能区分,接收的是一个对象,对象中能存放多个文件)
upload.fields([
{ name: "imgfile", maxCount: 3 },
{ name: "file", maxCount: 8 }
])
②对图片文件进行处理,先处理图片的缓存位置
③处理图片名字(注意处理好,否则会出现多个重名文件)
④处理保存的图片位置
⑤将处理好的图片名字拼接上线上的域名或ip地址,存进数据库
(我的代码里还有一些测试用的console.log,就不去删除了)
router.post(
"/addGoodsInfos",
upload.fields([
{ name: "imgfile", maxCount: 3 },
{ name: "file", maxCount: 8 }
]),
async (req, res) => {
console.log(req.body);
console.log(req.files);
let thumbnailList = [];
let imgList = [];
// 缩略图
if (req.files.imgfile) {
req.files.imgfile.forEach((value, index) => {
const fileData = fs.readFileSync(
path.resolve(__dirname, "../uploads/", value.filename)
);
let type = value.originalname.split(".")[1];
const filename = new Date().getTime() + "-" + index + "." + type;
const filePath = path.resolve(__dirname, "../public/", filename);
fs.writeFileSync(filePath, fileData);
thumbnailList.push("http://localhost:8080/" + filename);
});
}
// 详细信息图
if (req.files.file) {
req.files.file.forEach((value, index) => {
const fileData = fs.readFileSync(
path.resolve(__dirname, "../uploads/", value.filename)
);
let type = value.originalname.split(".")[1];
const filename = new Date().getTime() + "-" + index + "." + type;
const filePath = path.resolve(__dirname, "../public/", filename);
fs.writeFileSync(filePath, fileData);
imgList.push("http://localhost:8080/" + filename);
});
}
console.log(JSON.parse(req.body.info));
const info = JSON.parse(req.body.info);
console.log(thumbnailList);
console.log(imgList);
const goodsName = info.goodsName;
const imgUrl = JSON.stringify(thumbnailList);
const infoImgUrl = JSON.stringify(imgList);
const price = info.price;
const marketPrice = info.marketPrice || price;
const stock = info.stock || 0;
console.log(goodsName, imgUrl, infoImgUrl, price, marketPrice, stock);
const goods = new GoodsModel({
goodsName,
imgUrl,
infoImgUrl,
price,
marketPrice,
stock
});
await goods.save();
res.send({
code: 0,
msg: "添加商品成功",
data: goods
});
}
);