jjzjj

java MultipartFile+vue+element 批量上传文件、图片,与普通数据同时提交保存才上传到后端

愛芳芳 2023-08-18 原文

一.背景

文件上传项目可参考:点击预览

1.最简单也是最普遍的做法是form表单提交,其实前端提交到后端也是难以离开form表单提交,
一般有两种方式来处理文件、图片上传:

  1. 先上传,获取返回路径,再整个表单提交后端保存;
  2. 普通数据与文件图片同时提交后端,由后端处理

优点比较

  1. 第一种可以优先处理文件上传,异步处理,节省用户提交loading的时间,特别是一些大文件
  2. 第二种在最后提交才进行文件处理,没有脏数据,节省了文件服务器空间和流量

缺点比较,可以说刚好相反,第一种只有一选择文件,马上就上传,用户可以在最后提交之前一直change文件,就可能不断上传了一些没必要的文件图片,造成了各种文件脏数据,除非通过某些逻辑去删除这些脏文件(定时刷数据或提交的时候判断用户最终保存的数据来删除脏数据)

这里作者采取第二种方式,相对于第一种,实现难度稍微大些

二.前端html实现

element上传官方文档

on-success、on-error其实就是上面说的第一种方式才会用到的,作者感觉element就是推荐用异步的方式来实现的,通过action提交到指定上传接口

前端实现源码

<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>

同时定义属性

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

源码解析:

  • :limit=“9” //最多可上传9张图片
  • :before-upload=“beforeUpload”//上传之前,即选择图片后调用方法
  • :on-change=“handleChange”//选择图片上传调用方法
  • :on-preview=“handlePictureCardPreview”//预览图片调用方法
  • :disabled=“disabled”//是否禁用上传操作
  • :on-remove=“handleRemove”//上传已选择的图片

三.js方法实现

js源码

	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;
      },

源码解析:
方法意义上面已经说过了,其中this.form.files定义为一个数组,暂存上传的文件

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

组装数据请求上传到后端:

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;
})

四.java后端处理

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);
    }

源码解析:
作者一开始是想着用@RequestBody注解来接收整个数据对象的,但是这样的话会报错,具体错误信息作者没有记录下来,大概的意思就是MultipartFile类型不支持,没有构造方法那一类的,然后看了一下MultipartFile的源码

居然是interface的~,原来如此(理所当然认为应该是class的,哈哈哈,难怪),有更加深入研究的同学麻烦留言也分享一下,感谢!


java文件上传处理实现:

    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);
    }

有更加好的实现方式的,欢迎留言,大家分享,共同学习、共同进步~

有关java MultipartFile+vue+element 批量上传文件、图片,与普通数据同时提交保存才上传到后端的更多相关文章

  1. ruby - 我可以使用 aws-sdk-ruby 在 AWS S3 上使用事务性文件删除/上传吗? - 2

    我发现ActiveRecord::Base.transaction在复杂方法中非常有效。我想知道是否可以在如下事务中从AWSS3上传/删除文件:S3Object.transactiondo#writeintofiles#raiseanexceptionend引发异常后,每个操作都应在S3上回滚。S3Object这可能吗?? 最佳答案 虽然S3API具有批量删除功能,但它不支持事务,因为每个删除操作都可以独立于其他操作成功/失败。该API不提供任何批量上传功能(通过PUT或POST),因此每个上传操作都是通过一个独立的API调用完成的

  2. ruby-on-rails - Ruby 检查日期时间是否为 iso8601 并保存 - 2

    我需要检查DateTime是否采用有效的ISO8601格式。喜欢:#iso8601?我检查了ruby​​是否有特定方法,但没有找到。目前我正在使用date.iso8601==date来检查这个。有什么好的方法吗?编辑解释我的环境,并改变问题的范围。因此,我的项目将使用jsapiFullCalendar,这就是我需要iso8601字符串格式的原因。我想知道更好或正确的方法是什么,以正确的格式将日期保存在数据库中,或者让ActiveRecord完成它们的工作并在我需要时间信息时对其进行操作。 最佳答案 我不太明白你的问题。我假设您想检查

  3. ruby-on-rails - Ruby on Rails - 为文本区域和图片生成列 - 2

    我是Rails的新手,所以请原谅简单的问题。我正在为一家公司创建一个网站。那家公司想在网站上展示它的客户。我想让客户自己管理这个。我正在为“客户”生成一个表格,我想要的三列是:公司名称、公司描述和Logo。对于名称,我使用的是name:string但不确定如何在脚本/生成脚手架终端命令中最好地创建描述列(因为我打算将其设置为文本区域)和图片。我怀疑描述(我想成为一个文本区域)应该仍然是描述:字符串,然后以实际形式进行调整。不确定如何处理图片字段。那么……说来话长:我在脚手架命令中输入什么来生成描述和图片列? 最佳答案 对于“文本”数

  4. ruby-on-rails - 添加回形针新样式不影响旧上传的图像 - 2

    我有带有Logo图像的公司模型has_attached_file:logo我用他们的Logo创建了许多公司。现在,我需要添加新样式has_attached_file:logo,:styles=>{:small=>"30x15>",:medium=>"155x85>"}我是否应该重新上传所有旧数据以重新生成新样式?我不这么认为……或者有什么rake任务可以重新生成样式吗? 最佳答案 参见Thumbnail-Generation.如果rake任务不适合你,你应该能够在控制台中使用一个片段来调用重新处理!关于相关公司

  5. ruby-on-rails - 有没有办法为 CarrierWave/Fog 设置上传进度指示器? - 2

    我在Rails应用程序中使用CarrierWave/Fog将视频上传到AmazonS3。有没有办法判断上传的进度,让我可以显示上传进度如何? 最佳答案 CarrierWave和Fog本身没有这种功能;你需要一个前端uploader来显示进度。当我不得不解决这个问题时,我使用了jQueryfileupload因为我的堆栈中已经有jQuery。甚至还有apostonCarrierWaveintegration因此您只需按照那里的说明操作即可获得适用于您的应用的进度条。 关于ruby-on-r

  6. STM32读取串口传感器数据(颗粒物传感器,主动上传) - 2

    文章目录1.开发板选择*用到的资源2.串口通信(个人理解)3.代码分析(注释比较详细)1.主函数2.串口1配置3.串口2配置以及中断函数4.注意问题5.源码链接1.开发板选择我用的是STM32F103RCT6的板子,不过代码大概在F103系列的板子上都可以运行,我试过在野火103的霸道板上也可以,主要看一下串口对应的引脚一不一样就行了,不一样的就更改一下。*用到的资源keil5软件这里用到了两个串口资源,采集数据一个,串口通信一个,板子对应引脚如下:串口1,TX:PA9,RX:PA10串口2,TX:PA2,RX:PA32.串口通信(个人理解)我就从串口采集传感器数据这个过程说一下我自己的理解,

  7. 计算机毕业设计ssm+vue基本微信小程序的小学生兴趣延时班预约小程序 - 2

    项目介绍随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱小学生兴趣延时班预约小程序的设计与开发被用户普遍使用,为方便用户能够可以随时进行小学生兴趣延时班预约小程序的设计与开发的数据信息管理,特开发了小程序的设计与开发的管理系统。小学生兴趣延时班预约小程序的设计与开发的开发利用现有的成熟技术参考,以源代码为模板,分析功能调整与小学生兴趣延时班预约小程序的设计与开发的实际需求相结合,讨论了小学生兴趣延时班预约小程序的设计与开发的使用。开发环境开发说明:前端使用微信微信小程序开发工具:后端使用ssm:VU

  8. ruby-on-rails - 有没有一种工具可以在编码时自动保存对文件的增量更改? - 2

    我最喜欢的Google文档功能之一是它会在我工作时不断自动保存我的文档版本。这意味着即使我在进行关键更改之前忘记在某个点进行保存,也很有可能会自动创建一个保存点。至少,我可以将文档恢复到错误更改之前的状态,并从该点继续工作。对于在MacOS(或UNIX)上运行的Ruby编码器,是否有具有等效功能的工具?例如,一个工具会每隔几分钟自动将Gitcheckin我的本地存储库以获取我正在处理的文件。也许我有点偏执,但这点小保险可以让我在日常工作中安心。 最佳答案 虚拟机有些人可能讨厌我对此的回应,但我在编码时经常使用VIM,它具有自动保存功

  9. ruby-on-rails - Rails 3.2 防止使用错误保存对象 - 2

    我有一个ActiveRecord对象,我想在不对模型进行永久验证的情况下阻止它被保存。您过去可以使用errors.add执行类似的操作,但它看起来不再有效了。user=User.lastuser.errors.add:name,"namedoesn'trhymewithorange"user.valid?#=>trueuser.save#=>true或user=User.lastuser.errors.add:base,"myuniqueerror"user.valid?#=>trueuser.save#=>true如何在不修改用户对象模型的情况下防止将用户对象保存在Rails3.2中

  10. ruby-on-rails - 如何将大于 5GB 的文件上传到 Amazon S3? - 2

    我目前正在使用带有Carrierwavegem的Rails3.2将文件上传到AmazonS3。现在我需要能够处理用户提交的大于5GB的文件,同时仍然使用Carrierwavegem。Carrierwave或Fog是否有任何其他gem或分支可以处理5GB以上的文件上传到S3?编辑:我不想重写一个完整的Rails上传解决方案,所以像这样的链接没有帮助:https://gist.github.com/908875. 最佳答案 我想出了如何做到这一点,并且现在可以正常工作了。在正确的config/environment文件中,添加以下内容以

随机推荐