使用antd Upload +Java实现多张图片上传到后端服务器
主要实现功能:
- 前端多图片上传,控制在10个以内
- 后端接收多图片,并将图片打成压缩包
实现思路:
- antd.upload的action仅支持一次上传一个图片,所以自定义上传功能,将图片列表汇总后统一上传,后端使用HttpServletRequest接收。
前端实现(基于ant.design)
ant.design官网
– routes层,即页面渲染的部分
import {Upload} form ‘antd’;
class PicturesWall extends React.Component{
constructor(props){
super(props);
}
state = {
previewVisible:false,
previewImage:'',
fileList:[],
upFiles:[]
};
handleCancel=()=>{
this.setState({previewVisible:false});
}
handlePreview = async file =>{
if(!file.url && !file.preview){
file.preview = await getBase64(file.originFileObj);
}
this.setState({
previewImage: file.url || file.preview,
previewVisible: true
});
}
handleChange = (info) => {
this.setState({fileList: info.fileList});
}
beforeUpload = (file) => {
const {upFiles} = this.state;
upFiles.push(file);
this.setState({upFiles: upFiles});
}
addOk = () => {
const {upFiles, id} = this.state;
const formData = new FormData();
upFiles.forEach((file) => {
formData.append('file', file);
});
formData.append('id', id);
this.props.dispatch({
type: 'upload/upImage',
payload: {formData: formData}
})
}
render() {
const {previewVisible, previewImage, fileList} = this.state;
const uploadButton = (
<div>
<Icon type="plus" />
<div className="ant-upload-text">Upload</div>
</div>
)
return (
<div>
<Button type="primary" onClick={this.addOk()}>确认</Button>
<Upload
accept=".png,,jpg,.jpeg,.pdf"
listType="picture-card"
multiple={true}
fileList={fileList}
onChange={this.handleChange}
onPreview={this.handlePreview}
beforeUpload={this.beforeUpload}
>
{fileList.length >10 ? null : uploadButton}
</Upload>
<Modal visble={previewVisible} footer={null} onCancel={this.handleCancel()}>
<img alt="example" style={{width:'100%'}} src={previewImage}/>
</Modal>
</div>
)
}
}
function getBase64(file){
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => resolve(reader.result);
reader.onerror = error => reject(error);
});
}
– 这里省略module层
– service层,即与controller交互部分
export async function uploadInamge(params) {
return request(`/api/uploadImages`,
{
method: "POST",
body: params.formData
});
}
后端端实现(基于Java)
– controller层
@RequestMapping(value = "/uploadImages", method = RequestMethod.POST)
public RetCommon uploadImages(HttpServletRequest request) throws IOException{
RetCommon ret = new RetCommon(1000, "success");
MultipartHttpServletRequest params = ((MultipartHttpServletRequest) request);
String id = params.getParameter("id");
List<MultipartFile> files = ((MultipartHttpServletRequest) request).getFiles("file");
if(files == null || files.size()==0){
ret.setCodeMessage(1001,"未获取到有效文件");
}
try{
uploadService.uploadImages(files, id);
}catch (IOException e){
ret.setCodeMessage(1002, e.getMessage());
return ret;
}
return ret;
}
– uploadService层
public int uploadImages(List<MultipartFile> files, String id){
UUID uuid = UUID.randomUUID();
String filePath = path; // path为上传的路径
String zipTmpfile = filePath + File.separator+uuid.toString()+"image.zip";
ZipFile zipFile = new ZipFile(zipTmpfile);
for (int i = 0; i < files.size(); i++) {
MultipartFile file = files.get(i);
String fileName = file.getOriginalFilename();
if (fileName != null && !fileName.equals("")) {
String tmpfile = filePath + File.separator + uuid.toString() + fileName;
File tmpfileObj = new File(tmpfile);
file.transferTo(tmpfileObj);
ZipParameters parameters = new ZipParameters();
parameters.setCompressionMethod(Zip4JConstants.COMP_DEFLATE);
parameters.setCompressionLevel(Zip4JConstants.DEFAULR_LEVEL_MORMAL);
zipFile.addFile(tmpfileObj, parameters);
tmpfileObj.delete();
}
}
File ZipFileObj = new File(zipTmpfile);
String saveDirStr = filePath + File.separator + id; //id是关联的对象数据库中的id
File saveDir = new File(saveDirStr);
if(!saveDir.exists()){
if(!saveDir.mkdirs()){
logger.error("upload image mkdir error, dir path:"+saveDirStr);
return -1;
}
}
String newSavePath = saveDirStr + File.separator + "image.zip";
File targetFile = new File(newSavePath);
if(targetFile.exists()){
logger.info("delete old file"+newSavePath);
targetFile.delete();
}
if(!ZipFileObj.renameTo(new File(newSavePath))){
logger.error("move file error");
}
}
问题记录
- 对fileList理解有误,以为通过action会直接上传fileList,fileList是表示已上传的文件,但是定义是:新增一个图片时自动触发action操作上传,action只上传当前的file,不是fileList
<Upload fileList={fileList}>
与HttpServletRequest接收到的类型不一致,一开始直接上传这个fileList后端解析出来的files为空,后添加beforeUpload,在文件上传之前保存文件到新的列表中。