java MultipartFile+vue+element batch upload files and pictures, submit and save them at the same time as ordinary data before uploading to the backend

1. Background

Please refer to the file upload project: click to preview

1. The simplest and most common method is form submission. In fact, it is difficult to submit from the front end to the back end without form submission. There
are generally two ways to process file and image uploads:

  1. Upload first, get the return path, and then submit the entire form and save it on the backend;
  2. Ordinary data and file images are submitted to the backend at the same time and processed by the backend.

Advantage comparison

  1. The first one can prioritize file uploads and process them asynchronously, saving users time in submitting loading, especially for some large files.
  2. The second method only performs file processing after submission at the end. There is no dirty data, which saves file server space and traffic.

Comparing the disadvantages, it can be said that it is just the opposite. The first one only has to select a file and upload it immediately. The user can keep changing the file before the final submission, and some unnecessary file images may be continuously uploaded, resulting in various dirty files. Unless certain logic is used to delete these dirty files (regular data flushing or deletion of dirty data by judging the user's final saved data when submitting)

Here the author adopts the second method, which is slightly more difficult to implement than the first method.

2. Front-end html implementation

Element uploads official documents
Insert image description here
on-success and on-error. In fact, they are only used in the first method mentioned above. The author feels that element is recommended to be implemented in an asynchronous way, and is submitted to the specified upload interface through action.

Front-end implementation source code

<el-form-item label="图片" :required="form.postsType !== '2'">
              <el-upload
                action=""
                list-type="picture-card"
                :auto-upload="false"
                :limit="9"
                :before-upload="beforeUpload"
                :on-change="handleChange"
                :on-preview="handlePictureCardPreview"
                :disabled="disabled"
                :on-remove="handleRemove">
                <i class="el-icon-plus"></i>
              </el-upload>
              <div style="font-size: 12px;color: #666;">
                只能上传jpg/png文件,且不超过 2MB,最多上传 9 张图片
              </div>
              <el-dialog :visible.sync="dialogVisible">
                <img width="100%" :src="dialogImageUrl" alt="">
              </el-dialog>
            </el-form-item>

Also define attributes

	 dialogImageUrl: '',//窗口预览图片路径
     dialogVisible: false,//预览窗口是否打开
     disabled: false,//是否禁用上传操作

Source code analysis:

  • :limit=“9” //Up to 9 pictures can be uploaded
  • :before-upload=“beforeUpload”//Before uploading, the method is called after selecting the image.
  • :on-change=“handleChange”//Select image upload calling method
  • :on-preview=“handlePictureCardPreview”//Preview picture calling method
  • :disabled=“disabled”//Whether to disable upload operations
  • :on-remove=“handleRemove”//Upload selected image

3.js method implementation

js source code

	beforeUpload(file) {
    
    
        const isLt2M = file.size / 1024 / 1024 < 2;
        if (!isLt2M) {
    
    
          this.$message.error('上传头像图片大小不能超过 2MB!')
        }
        return isLt2M
      },
      handleRemove(file, fileList) {
    
    
        this.form.files = fileList;
        console.info(this.form);
      },
      handleChange(file, fileList){
    
    
        this.form.files = fileList;
        console.info(this.form);
      },
      handlePictureCardPreview(file) {
    
    
        this.dialogImageUrl = file.url;
        this.dialogVisible = true;
      },

Source code analysis:
The meaning of the method has been mentioned above, where this.form.files is defined as an array to temporarily store uploaded files.

form: {
    
    
  files: [],
  title: ''
},

Assemble the data request to upload to the backend:

let formData = new FormData();
for (const file of this.form.files) {
    
    //多个文件全部都放到files
  if(file.raw) {
    
    
    formData.append('files', file.raw);
  }
}
formData.append('title',this.form.title);
add(formData).then(res => {
    
    
  this.loading = false;
  if(res.code === 200){
    
    
    this.$message.success(res.msg);
  }
},error => {
    
    
  this.loading = false;
})

4.java backend processing

controller:

	@PostMapping("/add")
    @ApiOperation(value = "添加", notes = "添加")
    @ApiImplicitParams({
    
    
            @ApiImplicitParam(name = "title", value = "标题", required = true, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "files", value = "上传图片列表", required = false, dataType = "MultipartFile[]", paramType = "query")
    })
    public Result<Posts> add(
            @RequestParam("title")  String title,
            @RequestParam(value = "files",required = false) MultipartFile[] files
            ) {
    
    
        PostsReq postsReq = new PostsReq();
        postsReq.setTitle(title);
        postsReq.setFiles(files);
        return postsService.add(JwtUtil.getUserId(),postsReq);
    }

Source code analysis:
The author initially thought of using the @RequestBody annotation to receive the entire data object, but this would cause an error. The author did not record the specific error message. The general meaning is that the MultipartFile type is not supported and there is no constructor method. Then I read Check out the source code of MultipartFile

It's actually an interface~, so that's it (of course I think it should be a class, hahaha, no wonder), students who have done more in-depth research please leave a message and share it, thank you!

Insert image description here
Java file upload processing implementation:

    public String uploadImage(MultipartFile file) {
    
    
        if (file == null)
            throw new BizException("图片不能为空");

        //得到上传文件的文件名
        String fileName = file.getOriginalFilename();
        //以传入的字符串开头,到该字符串的结尾,前开后闭
        String suffixName = fileName.substring(fileName.lastIndexOf("."));
        long size = file.getSize();
        double mul = NumberUtil.div(size, (1024 * 1024), 2);
        // 自定义异常
        if (mul > 2)
            throw new BizException("图片大小不能大于2M");
        if (!isImage(suffixName))
            throw new BizException("不是图片格式");
        // 这里可以用uuid等 拼接新图片名
        String newFileName = UUID.randomUUID().toString().replace("-", "") + suffixName;
        // 创建路径
        String destFileName = fileUploadConfig.getImageRealPath() + File.separator + newFileName;
        File destFile = new File(destFileName);
        if (!destFile.getParentFile().exists())
            destFile.getParentFile().mkdirs();
        try {
    
    
            //将图片保存到文件夹里
            file.transferTo(new File(destFileName));
        } catch (IOException e) {
    
    
            e.printStackTrace();
            throw new BizException("图片上传错误");
        }
        //返回相对路径存储
        return fileUploadConfig.getImageMapperPath() + newFileName;
    }

    /**
     * 传进 .jpg  类似的格式 判断是否时图片格式
     * @param suffixName 图片格式后缀
     * @return
     */
    public static boolean isImage(String suffixName) {
    
    
        List<String> strings = Arrays.asList(".webp", ".png", ".jpg", ".jif", ".jpeg");
        return strings.contains(suffixName);
    }

If you have a better way to achieve it, please leave a message and share it with us to learn and make progress together~

Guess you like

Origin blog.csdn.net/lucky_fang/article/details/128677824