element的upload组件与fileupload使用

目录

一、使用upload的data属性携带表单数据提交

1、表单文本跟图片一起提交

2、只提交表单,不上传图片

3、后端接口的处理

二、使用upload的http-request属性,覆盖默认的上传行为,自定义上传的实现


这里主要讲表单与文件(图片)的上传提交

一、使用upload的data属性携带表单数据提交

1、表单文本跟图片一起提交

 这种情况下,账号昵称这些数据在表单,而加号的地方是upload组件,要上传的是图片,直接提交表单是无法将文件一起提交的。但是upload有一个参数data,如下图

 我们可以将表单数据绑定到upload,使用upload的提交方法携带表单数据一起提交。

//以下是upload组件部分
<el-upload
              ref="upload"   //注册组件信息不可少
              class="avatar-uploader"
              action="http://localhost:8085/Test/cou"  //提交的接口
              :show-file-list="false"
              :on-success="handleAvatarSuccess"
              :before-upload="beforeAvatarUpload"
              :data="addCourseForm"   //addCourseForm为表单数据
              :auto-upload="false"   
            >
              <img v-if="imageUrl" :src="imageUrl" class="avatar" />
              <i v-else class="el-icon-plus avatar-uploader-icon"></i>
            </el-upload>

//js部分,只需在函数中执行下面语句即可提交
this.$refs.upload.submit();

表单跟图片一起提交的实现大概就这样。但是又有新的问题,当只提交表单不上传文件时,使用upload的submit()提交不成功,测试后发现连请求都不会发出。原因还是在上面图片,官方文档写的很清楚了,data绑定的数据是文件上传的额外携带的参数,没有选择文件当然不会发出请求。

2、只提交表单,不上传图片

这种情况下,我们需要判断upload选择的图片数量,如果没有选择图片的话,使用常规的方式发起axios请求。

edit() {
      // 判断选择的文件数量
      if (this.$refs.upload.uploadFiles.length === 0) {
        let url = `http://localhost:8080/worryFree/CourseController/updateCourse`;
        this.$http
          .post(url, this.editCourseForm)
          .then((res) => {
            console.log(res);
            if (res.data.status === 205) {
              this.$message.success("修改成功!");
              //关闭对话框
              this.editCourseVisible = false;
              this.$message.success("修改成功!");
              //刷新课程列表
              this.getCourseList();
            }
          })
          .catch((error) => {
            console.log(error);
            this.$message("网络异常");
          });
      } else {
        this.$refs.upload.submit();
        //关闭对话框
        this.editCourseVisible = false;
        this.$message.success("修改成功!");
        //刷新课程列表
        this.getCourseList();
      }
    },

3、后端接口的处理

当然了,我们的后端接口肯定也要分情况处理,以下是代码

在这个类中,我将相关代码封装了一下。除了处理文件的上传,还用反射生成对象并注入属性值,用原生java写的,还是封装一些工具类比较方便。

package com.util;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

public class UploadUtil {
    /**
     * @param //
     * @return
     * @paramType
     * @Description 描述: 处理图片上传
     * @Author 李闪闪
     * @Date 2021/11/6 14:55
     */
    public static Map<String, String> upFile(HttpServletRequest req) throws Exception {
        //判断是否有上传文件
        if (ServletFileUpload.isMultipartContent(req)) {
            Map<String, String> map = new HashMap<>();
            DiskFileItemFactory fif = new DiskFileItemFactory();
            //设置文件缓冲区大小为4M
            fif.setSizeThreshold(1024 * 1024 * 4);
            //当上传文件超过缓冲区大小时,启用临时文件夹进行缓存(暂存)
            fif.setRepository(new File(req.getSession().getServletContext().getRealPath("/") + "tem"));
            ServletFileUpload upload = new ServletFileUpload(fif);
            //设置上传的单个文件的最大值是4M
            upload.setSizeMax(1024 * 1024 * 4);
            //解决中文路径或者文件名乱码问题
            upload.setHeaderEncoding("UTF-8");

            List<FileItem> items = upload.parseRequest(req);
            //System.out.println("列表"+items);
            Iterator<FileItem> it = items.iterator();
            while (it.hasNext()) {
                FileItem item = it.next();
                //1. 文本域
                if (item.isFormField()) {
                    //TODO:
                    String name = item.getFieldName();
                    //字段值是中文,以utf-8获取
                    String value = item.getString("utf-8");
                    map.put(name, value);
                }
                //2. 文件域
                else {
                    // 判断上传的文件是否是图片;非空则说明是图片
                    if (ImageIO.read(item.getInputStream()) != null) {
                        String fileName = item.getName();
                        if (fileName == null) {
                            throw new Exception();
                        }
                        String[] split = fileName.split("\\.");
                        String lastName = split[1];
                        String newName = UUIDUtil.getUUID() + "." + lastName;
                        // 设置文件上传路径(获取真实物理路径)
                        File file = new File(req.getSession().getServletContext().getRealPath("/") + "img", newName);
                        item.write(file);
                        map.put("images", newName);
                    } else {
                        System.out.println("非图片!");
                    }
                }
            }
            return map;
        }
        return null;
    }

    /**
     * @param //[map, obj]
     * @return java.lang.Object
     * @paramType [java.util.Map<java.lang.String, java.lang.String>, java.lang.Class<?>]
     * @Description 描述: 获取请求中的文本域和文件名,利用反射自动注入对象
     * @Author 李闪闪
     * @Date 2021/11/6 14:41
     */
    public static Object reObj(Map<String, String> map, Class<?> obj) {
        Object o = null;
        try {
            o = obj.newInstance();
            Field[] fields = obj.getDeclaredFields();
            for (Map.Entry<String, String> str : map.entrySet()) {
                for (Field field : fields) {
                    //允许通过反射访问该字段
                    field.setAccessible(true);
                    String name = field.getName();
                    if (name.equals(str.getKey())) {
                        if (int.class == field.getType()) {
                            field.set(o, Integer.parseInt(str.getValue()));
                        } else if (long.class == field.getType()) {
                            field.set(o, Long.parseLong(str.getValue()));
                        } else if (double.class == field.getType()) {
                            field.set(o, Double.parseDouble(str.getValue()));
                        } else {
                            field.set(o, str.getValue());
                        }
                    }
                }
            }
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return o;
    }

    /**
     * @param //[req, obj]
     * @return java.lang.Object
     * @paramType [javax.servlet.http.HttpServletRequest, java.lang.Class<?>]
     * @Description 描述: 没有文件时自动获取请求中的参数,注入对象
     * @Author 李闪闪
     * @Date 2021/11/6 15:13
     */
    public static Object reObj(HttpServletRequest req, Class<?> obj) throws InstantiationException,
            IllegalAccessException {
        Object o = obj.newInstance();
        Field[] fields = obj.getDeclaredFields();
        for (Field field : fields) {
            //允许通过反射访问该字段
            field.setAccessible(true);
            String name = field.getName();
            String param = req.getParameter(name);
            if (param != null) {
                if (int.class == field.getType()) {
                    field.set(o, Integer.parseInt(param));
                } else if (long.class == field.getType()) {
                    field.set(o, Long.parseLong(param));
                } else if (double.class == field.getType()) {
                    field.set(o, Double.parseDouble(param));
                } else {
                    field.set(o, param);
                }
            }
        }
        return o;
    }

以下是我的使用方式,贴出来的只是servlet的一个方法:

/**
    * @paramType [javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse]
    * @param //[req, resp]
    * @return void
    * @Description 描述: 添加sku
    * @Author 李闪闪
    * @Date 2021/11/6 16:13
    */
    public void addSku(HttpServletRequest req, HttpServletResponse resp) {
        try {
            req.setCharacterEncoding("utf-8");
            Skus skus = null;
            //进入处理文件的方法
            Map<String, String> map = UploadUtil.upFile(req);
            if (map != null){
                //map不为空,则有文件上传
                skus = (Skus) UploadUtil.reObj(map, Skus.class);
            }else{
                //只有表单数据时,直接传入req生成对象,需要注意的是,不管是map中的key还是req中的参数名都应该与实体类属性名一样,否则映射不成功,自然也就无法正确注入属性值
                skus = (Skus) UploadUtil.reObj(req,Skus.class);
            }
            skus.setDate(DateCaseUtil.dateToStr());
            skuService.createSkus(skus);
            ReMessTo.toRespone(resp,ResponseDataUtil.buildCreate("添加成功"));
        } catch (Exception e) {
            e.printStackTrace();
            ReMessTo.toRespone(resp,ResponseDataUtil.buildError("添加失败"));
        }
    }

二、使用upload的http-request属性,覆盖默认的上传行为,自定义上传的实现

这种方式是后来在朋友的启示下发现的,我一开始并不知道http-request是这样用的,http-request指向的函数会有一个element 的默认回调参数 定义为param

这种方式 正好跟上面用data的方式相反,data是upload携带表单数据,http-request则大概可以理解为将upload的文件数据提取出来,添加到表单数据中。

<el-upload class="upload-demo" drag action="https://jsonplaceholder.typicode.com/posts/" :file-list="fileList"
                    :http-request="getFile" :multiple="false">
                    <i class="el-icon-upload"></i>
                    <div class="el-upload__text">
                        <p style="margin:0px;">点击上传</p>
                        <p style="margin-top:0px;color: rgba(28,31,35,0.8); font-weight: 500;text-align: center;">
                            或直接将文件拖入此区域</p>
                        
                    </div>

                </el-upload>
getFile(item) {
                this.file = item.file;
            },
addVideo() {
                //FormData对象,它的api文档在这里:https://developer.mozilla.org/zh-CN/docs/Web/API/FormData/FormData

                const fd = new FormData()
                //以下是我的其他表单数据
                fd.append('uid ', this.uid);
                fd.append('title ', this.title);
                fd.append('vtype ', this.vtype);
 
                //将文件数据添加进FormData对象
                fd.append('filename', this.file);
                //设置请求头
                const config = { headers: {'Content-Type': 'multipart/form-data'} };
                let url = `http://localhost:8088/upload/addVideo
                this.$http.post(url,fd,config).then(res => {
                    console.log(res.data.data);
                });


            }

这种方式比上面的简单多了,还是这种好。

后端接口代码跟上面大体相似,代码还有很大的优化空间。

水平有限,主要是记录一下自己的成长,有什么错误的烦请大佬们指正。

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值