Vue + Springboot achieve avatar upload function

Vue + Springboot achieve avatar upload function

Foreword

Recently started project a separate front and rear ends, the front end with the Vue + ElementUI, the rear end is realized using Springboot + mybatis. Because I am completely on my own for the first time a person before and after the writing end, so to record their own problems. If you are into 上传文件such a function and a headache, you can take a look at the article I wrote, I hope you can help. Ado, let's go directly to the topic.

The front section

Page code

Here with the upload component ElementUI, mainly to write good-looking style than his point, in fact, is the same mark, the main attention to the data format at the time of submission !!!

<el-upload
   ref="upload"
   class="avatar-uploader"
   action="#"
   accept="image/png,image/jpg,image/jpeg"
   :auto-upload="true"
   :limit="1"
   :show-file-list="false"
   :before-upload="beforeAvatarUpload"
   :http-request="uploadHead"
   :on-success="handleAvatarSuccess"
 >
   <img v-if="userInfo.headImage" :src="userInfo.headImage" class="avatar">
   <i v-else class="el-icon-plus avatar-uploader-icon"></i>
 </el-upload>

js code

When uploading files need to be sent with the request data FormData format, used here vue-axios fulfill the request example, using ajax junior partner is the same Oh! As long as the incoming FormData format of the data in the ajax data can be.

async uploadHead(f) {
   // console.log(f);  // 感兴趣的小伙伴可以在控制台输出下这里
   let fd = new FormData(); //通过form数据格式来传
   fd.append("file", f.file); 
   // console.log(fd.get('file')); 
   let res = await this.$http.uploadHead(fd, {
     headers: { 'Content-Type': 'multipart/form-data' }
   });
   console.log(res);
 }

It should be noted that we are using fd.append("file",f)does not work, why, changed fd.append ( "file", f) we send the next request
Here Insert Picture Description
can see the request in advance did send a FormData data, but in the back-end processing such occurs when the request 400 error, we need not such a data, the following may be of interest to a small partner in the output console in the front end of what we selected files f
Here Insert Picture Description
you can see the output of an object, and this object but also contains a file object, this is the data that we need to pass, so when you need to send a request to the file object is passed to the back-end, use the "object. attribute name," the way to get to the appropriate values, let us send a request to
Here Insert Picture Description
see request parameters become binary format, which is the data we need

The rear end portion

Because we do not proficient on java, so how back-end processing file requests really knew nothing, in the studious attitude, ultimately, find a way

@PostMapping("/uploadHead")
@ResponseBody
public ServerResponse uploadHead(@RequestParam("file") MultipartFile file, HttpServletRequest request) {
	String path = request.getServletContext().getRealPath("/"); // 获取服务器所在地址
	String url = request.getContextPath() + "/headImage/";
	File filePath = new File(path);
	System.out.println("文件的保存路径:" + path);
	if (!filePath.exists() && !filePath.isDirectory()) {
    	System.out.println("目录不存在,创建目录:" + filePath);
    	filePath.mkdirs(); // mkdir()不会创建目录,找不到相应路径时返回false;而mkdirs()当目录不存在时则会创建相应目录
	}
	//获取原始文件名称(包含格式)
    String originalFileName = file.getOriginalFilename();
    //获取文件类型,以最后一个`.`为标识
    String type = originalFileName.substring(originalFileName.lastIndexOf(".") + 1);
    HttpSession session = request.getSession();
    String userId = Integer.toString((Integer)session.getAttribute("userId"));
    String fileName = userId + "."+ type; // 新文件名,这里可以根据需要改名
    //在指定路径下创建一个文件
    File targetFile = new File(path, fileName); // 未使用outputStream.write()的时候,是一个File对象,保存在内存中,硬盘中看不到,但是可以使用这个对象
    try {
        // 使用springmvc的transferTo方法上传文件
        file.transferTo(targetFile);
        UserInfo userInfo = new UserInfo();
        userInfo.setHeadImage(url + fileName);
        userInfo.setUserId((Integer)session.getAttribute("userId"));
        int i = userService.updateUserInfo(userInfo);
        if (i != 0) {
            return ServerResponse.createBySuccess("头像上传成功", url + fileName);
         }
    } catch (IOException e) {
        e.printStackTrace();
    }
    return ServerResponse.createByError("头像上传失败");
}

After the treatment is successful, we look at the database to save the appropriate path, and file system to save the corresponding file
Here Insert Picture Description
Here Insert Picture Description
which is to get to the top of the path, the path is springboot built temporary address tomcat, so each time you start the project when springboot , directory names are not the same. In this route does save the corresponding file, the database does hold the appropriate path.
But such a path, how to access the front-end to it?
Here we must look at the front end of a proxy, in vue.config.jsthe configuration in cross-domain

module.exports = {
    devServer: {
        open: false,// 自动打开浏览器
        host: 'localhost',
        port: 8080,
        https: false,
        hotOnly: false,
        disableHostCheck: true,//Invalid Host header
        proxy: { // 配置跨域
            '/alumni': {
                target: 'http://localhost:8081', // 这是后端地址
                ws: true,
                changOrigin: true,
                pathRewrite: {
                  '^/alumni': '/alumni' 
                }  
            }
        },
        before: app => { }
    }
}

After everything is ready, open our pages to view the next picture if uploaded successfully

Here Insert Picture Description
You can see the empty, why? Acting also set up, the front end Why can not access the pictures? To find out, we visit in the address bar localhost:8081/alumni/headImage/2.png, the result is a lovely 404 pages.

As for the reason why I do not know, just know that if it is ssm project, using our own local Tomcat when request.getServletContext().getRealPath("/")acquired is the address of the project, namely the server address of the project (for the time being so understanding it); and we springboot mentioned above also return but it is a random address each time you start the project when the directory name is not the same, such an address in the project 发布上线after can not control (the above methods can not change), but 开发阶段it is not; in addition , springboot project default static resources need to be placed in a static directory of resources, files in this directory can be accessed directly via the back-end address

So, we need to request.getServletContext().getRealPath("/")change ResourceUtils.getURL("classpath:").getPath() + "static/headImage/"so that you can access during the development phase to.

The first blog, there may be a large expression is not clear, and hope you will forgive me, I hope to be able to help you.

Published an original article · won praise 1 · views 42

Guess you like

Origin blog.csdn.net/Xiaoming985/article/details/104974978