基于vue+springboot的文件上传(并未前后端分离)
程序员文章站
2022-07-01 16:32:33
前言注:本文主要处理前端如何向后端传参以及后端如何处理今天在使用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>
本文地址:https://blog.csdn.net/haa252259386/article/details/110153650