基于vue+springboot的文件上传(异步请求)

前言

注:本文主要处理前端如何向后端传参以及后端如何处理

今天在使用vue+springboot实现文件上传的时候遇到了诸多问题,查找相关资料的时候都太散乱了,导致整了一下午才真正完成了文件上传功能,所以在此总结一下整个流程,以及需要主要的点,以便以后再次使用,同时让一些像我这样学了一半就开跑的人少走些弯路

后端部分

在这里我先讲后端部分,后端的实现其实相较于前端更为简单(可能因为我个人比较熟悉后端)

后端处理上传而来的文件分为以下几步

  • 获取项目的绝对路径
  • 创建文件目录
  • 创建文件
  • 上传文件到服务器本地

那么下面直接结合注释看代码吧

需要导入的包(springboot的包就不说了,在这里只是讲文件上传)

<!--这个包就是可以使用FileNameUtils-->
<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.4</version>
</dependency>

具体代码,能做注释的都做了

结合注释阅读吧

package com.zhage.controller;


import org.apache.commons.io.FilenameUtils;
import org.springframework.util.ResourceUtils;
import org.springframework.web.bind.annotation.PostMapping;
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 java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

@RequestMapping("file")
@RestController
public class FileController {

    /**
     * 传入的参数是MultipartFile
     * 加入@RequestParam注解表示该参数一定要接受到,接受到的是前端的file
     * 根据自己需求可以有其他参数,这里就演示文件上传
     * @param mf
     * @return
     */
    @PostMapping("upload")
    public String upload(@RequestParam("file")MultipartFile mf) throws IOException {

        /**
         * 获取项目绝对路径
         * 最终文件上传是需要绝对路径的
         * 相当于给要上传的位置定个坐标
         * classpath:就可以去获得resources的目录
         * 具体classpath:获得resources的原因就得自己去探索了,本文主要是讲文件上传
         * 这里不去除first的话这个路径开头会有一个/,虽然没有什么影响
         */
        String absPath = ResourceUtils.getURL("classpath:").getPath().replaceFirst("/","") + "static/files";
        /**
         * 创建文件目录
         * 根据自己的需求
         * 在这我就以当前时间创建
         */
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd-HH-mm");
        //文件的目录应该为绝对路径+目录名
        String dirPath = absPath+"/"+sdf.format(new Date());
        //通过这个路径创建目录
        File dir = new File(dirPath);
        //如果不存在就创建该目录
        if(!dir.exists()){
            dir.mkdirs();
        }
        /**
         * 创建文件
         * 文件名字就根据自己的需求而定
         * 我这里为了方便,就叫cutezha吧
         */
        //先获取文件本身的名字
        String oldName = mf.getOriginalFilename();
        //使用FileNameUtils获取扩展名,这里获取的没有.所以手动加上
        String extension = "."+FilenameUtils.getExtension(oldName);
        String fileName = "cutezha"+extension;
        //上传文件
        mf.transferTo(new File(dir,fileName));
        /**
         * 将数据返回给前端,我这里就直接将路径返回了
         * 注意这里用dirPath才是斜杠,如果使用dir则是反斜杠
         */
        return dirPath+"/"+fileName;
    }
}

那么后端就完成了,其中有些可以根据自己的需求更改,下面就是前端,由于我本身前端学的一塌糊涂,所以注释就较少

前端部分

前端部分由于学的很差,所以理解可能没后端这么好,希望指出

前端上传也可分为以下几步

  • 上传文件到input
  • 获取input里的文件
  • 通过axios异步传给后端存入服务器本地

原生vue的axios异步

这里通过axios请求了/file/upload,下面直接看前端代码

<!doctype html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport"
              content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Document</title>
        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
        <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
    </head>
    <body>
        <div id="app">
            <form action="">
                <!--给该input标签绑定了change事件,绑定到了iii并且通过$event将该标签传递进去-->
                文件上传:: <input type="file" @change="iii($event)" ref="file">
                <input type="button" @click="submitForm">
            </form>
        </div>
        <script type="text/javascript">
            const app = new Vue({
                el: '#app',
                data() {
                    return {
                        file: ''
                    };
                },
                methods: {
                    submitForm: function (event) {
                        /**
                     * 这句也可以获得file
                     * this.file = this.$refs.file.files[0];
                     * 甚至可以通过原生js实现
                     */
                        //通过formdata将文件存入
                        //除了file,可以将想要向后端传递的参数写进fd
                        fd = new FormData();
                        fd.append("file", this.file);
                        axios({
                            url: 'http://localhost:8080/file/upload',   //所要请求的地址
                            data: fd,       //携带的参数
                            method: 'post',   //请求方式
                            headers: {
                                //请求头很重要,我看见有人说可以不写,但我不写不行
                                'Content-Type': 'multipart/form-data',
                            }
                        }).then((res)=>{
                            console.log(res.data);
                        });
                    },
                    iii:function (e){
                        //次函数主要是将input里的文件存入data里的file里
                        alert(e.target);
                        this.file=e.target.files[0];
                    }
                }
            })
        </script>
    </body>
</html>

运行效果

由于我在iii函数中弹出了一下
在这里插入图片描述

在这里插入图片描述

点击上传
在这里插入图片描述

去文件夹查看

在这里插入图片描述

使用elementui下的el-upload组件

不太清楚该组件的底层原理是如何实现的,这里就把代码贴上吧,原理还是一样的,但是file本来就在组件里面,就不用了获取了,传入其他你想要的参数就可以了,这里就不再掩饰

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>欢迎注册</title>
        <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
        <script src="https://unpkg.com/element-ui/lib/index.js"></script>
        <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
    </head>
    <body>
        <div class="login-box" id="app" >
            <el-form >
                <!--action="http://localhost:8181/ctbuc/file/upload"-->
                <el-form-item label="头 像:" prop="userimg">
                    <el-upload
                               class="avatar-uploader"
                               :show-file-list="false"
                               action="http://localhost:8080/file/upload"
                               :data="你要传的"
                               >
                        <img v-if="imageUrl" :src="imageUrl" class="avatar">
                        <i v-else class="el-icon-plus avatar-uploader-icon"></i>
                    </el-upload>
                </el-form-item>
            </el-form>
        </div> 
    </body>
后面js没啥好看的,因为都在elupload里处理完了

</html>


                  <i v-else class="el-icon-plus avatar-uploader-icon"></i>
                    </el-upload>
                </el-form-item>
            </el-form>
        </div> 
    </body>
后面js没啥好看的,因为都在elupload里处理完了

</html>
已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 游动-白 设计师:上身试试 返回首页