需求
使用vant的图片上传组件上传图片,后台接收图片并存储到服务器,并且返回图片地址和存储id
前端
HTML:
<van-field :readonly=detailFlag autosize name="code" label="上传图片" placeholder="请输入">
<template #input>
<van-uploader v-model="uploader"
multiple
accept="image/*"
:before-read="beforeRead"
:max-count="5"
:max-size="3 * 1024 * 1024"
@oversize="onOversize"
:after-read="afterRead"
@delete="deleteFile"
/>
</template>
</van-field>
js:
import {uploadMultipleFile} from "../../api/target/file";
import Toast from "vant/es/toast";
//校验文件大小是否超出限制
onOversize(file){
Toast.fail('文件太大');
},
//校验图片格式
beforeRead(file){
let fileType='';
if(file instanceof Array && file.length){
for (let i = 0; i < file.length; i++) {
fileType=file[i].type.substr(0,file[i].type.indexOf('/'));
if (fileType !== 'image') {
Toast('格式错误');
return false;
}
}
}else{
fileType=file.type.substr(0,file.type.indexOf('/'));
if (fileType!== 'image') {
Toast('格式错误');
return false;
}
}
return true;
},
//上传图片
afterRead(file){
console.log("上传文件"+file);
file.status = 'uploading';
file.message = '上传中...';
let formData = new FormData();
//区分单文件上传还是多文件
if(file instanceof Array && file.length){
for (let i = 0; i < file.length; i++) {
formData.append("files", file[i].file);
}
}else{
formData.append("files", file.file);
}
uploadMultipleFile(formData).then(res => {
console.log("上传图片结果报文", res);
if (res.data.code =='200' ){
if(file instanceof Array && file.length){
for (let i = 0; i < file.length; i++) {
this.storeId.push(res.data.data.storeIds[i]);
}
}else{
this.storeId.push(res.data.data.storeIds[0]);
}
console.log("storeIds");
console.log(this.storeId);
// Toast.success('上传图片成功');
} else{
file.status = 'failed';
file.message = '上传失败';
Toast.fail('上传图片失败');
}
}).catch(err => {
file.status = 'failed';
file.message = '上传失败';
console.log(err);
});
},
//删除图片
deleteFile(file,detail){
console.log("删除");
this.storeId.splice(detail.index,1);
console.log("storeIds");
console.log(this.storeId);
}
此处是使用form-data格式传值,请求方式使用的是axios
使用form-data格式传值和使用普通的body传值方法(raw)是一样的,无非是form-data要把数据提前处理好而已,需要注意的是在请求的时候不用设置Content-Type,因为发送请求时会自动识别
注意:这里不能直接将方法获取到的file当做参数传过去,因为这个file是被包装过的,我们要的是里面的那个精华,像是这样:
formData.append("files", file.file);
本人便是在这里卡了四五个小时。。。
api:
index.js:
import axios from 'axios'
import setRequestHeader from "../../utils/setHeaderData"
const service = axios.create({
baseURL:"http://ip:port/",
responseType: 'json',
timeout: 10000,
...setRequestHeader
});
export default service
file.js:
import {createSerialNumber} from "../../utils/random.js"
import axios from "./index.js"
/**
* 图片上传
* @param {Object} obj
*/
export function uploadMultipleFile(obj) {
obj.seqno = createSerialNumber;
return axios({
url: 'store/uploadMultipleFile',
method: 'post',
data: obj
});
}
后端
controler:
public Response uploadImg(@RequestParam("files")MultipartFile[] files,HttpServletRequest request){
if (files.length==0){
return new Response("fail","无文件");
}
try {
return new Response("success",storeService.uploadImg(files, request));
} catch (IOException e) {
e.printStackTrace();
return new Response("fail",e.getMessage());
}
}
service:
HashMap uploadImg(MultipartFile[] files, HttpServletRequest request) throws IOException;
serviceImpl:
@Override
public HashMap uploadImg(MultipartFile[] files, HttpServletRequest request) throws IOException {
HashMap map=new HashMap();
List<String> images = new ArrayList<>();
List<String> storeIds = new ArrayList<>();
for (MultipartFile file : files) {
//获取绝对路径
String realPath = uploadFileConfig.getFilePath();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd/");
String format = sdf.format(new Date());
//文件存放的目录
File folder = new File(realPath + format);
if (!folder.isDirectory()) {
folder.mkdirs();
}
String oldName = file.getOriginalFilename();
//文件后缀
String suffix = oldName.substring(oldName.lastIndexOf("."));
//文件新名字
String newName = UUID.randomUUID().toString() + suffix;
File targetFile = new File(folder+"/"+newName);
if (!targetFile.exists()) {
targetFile.mkdirs();
} else {
targetFile.delete();
}
file.transferTo(targetFile);
String filePath = "uploadFile/" + format + newName;
String storeId = editStore(filePath, "");
images.add(filePath );
storeIds.add(storeId);
}
map.put("images",images);
map.put("storeIds",storeIds);
return map;
}
application.yml:
upload:
filepath: D:/upload/test/uploadFile/
configuration:
@Component
@ConfigurationProperties(prefix = "upload")
@Data
public class UploadFileConfig {
private String filePath;
}
效果