记一次图片前端传后端遇到的各种大坑。
先阐述几个难点 授人以鱼不如授人以渔 有则共勉,重点已加粗 文章最后再附上源码。

  1. 第一点就是打开电脑窗口 怎么实现按住ctrl可以多选文件: (注) accept : 接收类型; image/* : 所有类型图片; 重点 multiple: 多选
1.  <input type=“file” @change=“getImgBase()” name=“file” accept=“image/*” multiple>

js部分:获取window事件 即打开windows窗口 及选中的文件

var event = event || window.event;
 var fileList = event.target.files;

2.预览需要转base64 在相应代码处有注释

3.将选中的图片存入数组 再遍历存入到FormData()中 FormData.append(name,file)实现追加,name值可以为固定 不会被覆盖,FormData() 直接console.log 打印出来为空! 所以这就是错觉 formdata().append为空 以为没有成功追加,用FormData.getAll(“file”) 输出就能看到file了 (在文章代码中有体现)

4.同理 后端接收用 MultipartFile[] 也可能为空,需要设置请求头Content-Type:headers: {‘Content-Type’: ‘multipart/form-data’}, 在axios中 直接把这句写进去就可以了

5.通常至此就可以了,除非遇到像我一样的情况,设置请求头还可能为空,思考是不是不应该用MultipartFile[] 可是写HttpServletRequest,request里面也找不到file,那基本可以确定 东西就是没有传过来 和拿什么接收没有关系,因为只要传过来 原生servlet里面一定会有 框架等都是基于servlet封装 , 换句话说 哪怕不是springboot springmvc框架,java后端一样可以取到 ,去request里面取即可 debug看request里面内容。这里有个拓展 也是在完成之后发现的:

//MultipartFile[] file, HttpServletRequest request 两个参数2写1即可,
// MultipartFile就是集成了HttpServletRequest 
 public JSONObject updatePic(@RequestParam(value = "file",required = false) MultipartFile[] file, HttpServletRequest request)throws Exception{
 }

前端如何上传图片给java后台 前端上传图片到后端vue_前端如何上传图片给java后台

6.言归正传,console.log FormData.getAll(“file”)里面是有东西的,说明是传输过程出错,再次确认, 设置了headers: {‘Content-Type’: ‘multipart/form-data’}, 但是按F12发现content-type 还是application/json,为什么设置无效?

终于发现有个细节:axios (文中代码已封装成this.api 其实是一样的) 里面写的是params:param 需要改成data:param。因为代码中采用的是post方式, params实际是添加到url请求字符串中,而data才是添加到请求体中,即:data对应post,params对应get, 改成data后F12发现content-type改成功了

前端如何上传图片给java后台 前端上传图片到后端vue_spring boot_02

file及request都有数据 有图有真相 只上传自己亲测有效的代码:

前端如何上传图片给java后台 前端上传图片到后端vue_spring boot_03


前端如何上传图片给java后台 前端上传图片到后端vue_spring_04

import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;

/**
 * java部分 
 */
@RestController
@RequestMapping("/picture")

public class PictureController {
    @Autowired
    private PictureService pictureService;
    @RequestMapping("updatePic")
    @Transactional(rollbackFor = Exception.class)
    public JSONObject updatePic(@RequestParam(value = "file",required = false) MultipartFile[] file, HttpServletRequest request)throws Exception{
    // 逻辑根据自己需要写 至此参数file已经能取到前端的传值
        //pictureService.updatePic(file,request);
        //return CommonUtil.successJson();
    }

}

vue代码: 用的csdn js代码块上传的,识别有误 其实没有被注释 直接复制进vue里面就行了

<template>
  <div class="app-container">

    <div style="float: right;">
      <el-button type="primary" icon="plus" @click="updatePic()">上传
      </el-button>
    </div>

    <div class="image-view">
      <el-form>
        <el-form-item>
          <div class="addbox">
            <!-- accept : 接收类型;    image/*  : 所有类型图片;   multiple: 多个     -->
            <input type="file" @change="getImgBase()" name="file" accept="image/*" multiple>
            <div class="addbtn">+</div>
            <div class="texttips"> 添加图片</div>
          </div>
        </el-form-item>
      </el-form>
      <div class="view">
        <div class="item" v-for="(item, index) in imgfilesPre">
          <span class="cancel-btn" @click="delImg(index)">x</span>
          <img :src="item">
        </div>
      </div>
    </div>

  </div>
</template>
<script>
  export default {

    data() {
      return {
        imgfilesPre: [],      // 图片预览地址
        imgfiles: [],  // 图片原文件,上传到后台的数据

      }
    },
    methods: {
      //获取图片base64实现预览
      getImgBase() {
        var _this = this;
        var event = event || window.event;
        var fileList = event.target.files;
        let length = fileList.length;

        for (let i = 0; i < length; i++) {
          var reader = new FileReader();
          _this.imgfiles.push(fileList[i]);
          reader.readAsDataURL(fileList[i]);

          //转base64 base 64 图片地址形成预览
          reader.onload = function (e) {
            _this.imgfilesPre.push(e.target.result);
          };
        }
        // 防止不能连续选同一图片
        event.target.value = "";
      },

      //删除图片
      delImg(index) {
        this.imgfilesPre.splice(index, 1);
      },

      // 上传图片至服务端
      updatePic() {
        var param = new FormData();
        var length = this.imgfiles.length;
        for (let i = 0; i < length; i++) {
          let file = this.imgfiles[i];

          console.log(file, file['name'])
          param.append('file', file, file['name'])
        }
        console.log(param.getAll("file"))

        this.listLoading = true;

        this.api({
          /*开启withCredentials后,服务器才能拿到cookie 跨域请求时是否需要使用凭证*/
          withCredentials: true,
          headers: {'Content-Type': 'multipart/form-data'},
          url: '/picture/updatePic',
          method: 'post',
          data: param

        })
      },
    }
  }
</script>
<style scoped>

  .image-view {
    width: auto;
    margin: 50px auto;

  }

  .image-view .addbox {
    margin: 0 auto;
    position: relative;
    height: 100px;
    width: 100px;
    margin-bottom: 20px;
    text-align: center;
  }

  .image-view .addbox input {
    position: absolute;
    height: 100px;
    width: 100px;
    opacity: 0;
    text-align: center;
  }

  .image-view .addbox .addbtn {

    height: 100px;
    width: 100px;
    line-height: 100px;
    color: #fff;
    font-size: 40px;
    background: #ccc;
    border-radius: 10px;
    text-align: center;
  }

  .image-view .texttips {
    color: #001528;
    text-align: center;
  }

  .image-view .item {
    position: relative;
    float: left;
    height: 100px;
    width: 100px;
    margin: 10px 10px 0 0;
  }

  .image-view .item .cancel-btn {
    position: absolute;
    right: 0;
    top: 0;
    display: block;
    width: 20px;
    height: 20px;
    color: #fff;
    line-height: 20px;
    text-align: center;
    background: red;
    border-radius: 10px;
    cursor: pointer;
  }

  .image-view .item img {
    width: 100%;
    height: 100%;
  }

  .image-view .view {
    clear: both;
  }
</style>