SpringBoot+Vue 文件上传
vue
vuejs/vue: 是一个用于构建用户界面的 JavaScript 框架,具有简洁的语法和丰富的组件库,可以用于开发单页面应用程序和多页面应用程序。
项目地址:https://gitcode.com/gh_mirrors/vu/vue

·
SpringBoot后台
1. application.properties配置文件
在application.properties配置文件中设置文件上传属性
#是否开启文件上传支持,默认是true
spring.servlet.multipart.enabled=true
#文件写入磁盘的阈值,默认是0
spring.servlet.multipart.file-size-threshold=0
#单个文件的最大值,默认是50MB
spring.servlet.multipart.max-file-size=50MB
#多个文件上传时的总大小 值,默认是100MB
spring.servlet.multipart.max-request-size=100MB
#是否延迟解析,默认是false
spring.servlet.multipart.resolve-lazily=false
#自定义文件访问路径
myfile.path=C:\\File
2. Controller文件
本项目采用Maven方式,导入代码后,如有代码报错,在IDEA中按“Alt+Enter”可导入所需要的依赖包
// controller
package com.SpringBoot.SpringStudy.controller;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
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;
@Slf4j
@RestController
public class FileController {
@Value("${myfile.path}")
private String filePath;
// 单文件上传功能
@RequestMapping(value = "/uploadSingleFile", produces = "application/json;charset=utf-8")
public String uploadSingleFile(@RequestParam("file") MultipartFile multipartFile) {
String info = null;
String fileName = multipartFile.getOriginalFilename();
File file = new File(filePath + '\\' + fileName);
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
info = ("父级文件目录不存在,已创建目录");
}
try {
multipartFile.transferTo(file);
} catch (IOException e) {
info = ("程序错误,请重新上传" + e);
e.printStackTrace();
} finally {
info = ("文件上传成功,文件全路径名称为:{}" + file.getPath());
}
return info;
}
// 多文件上传功能实现
@PostMapping("/uploadMultipleFile")
public String uploadMultipleFile(@RequestParam("file") MultipartFile[] multipartFiles) {
String info = null;
for (MultipartFile multipartFile : multipartFiles) {
String fileName = multipartFile.getOriginalFilename();
File file = new File(filePath + '\\' + fileName);
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
info = ("父级文件目录不存在,已创建目录");
}
try {
multipartFile.transferTo(file);
} catch (IOException e) {
info = ("程序错误,请重新上传" + e);
e.printStackTrace();
} finally {
info = ("文件上传成功,文件全路径名称为:" + file.getPath());
}
}
return info;
}
}
SpringBoot采用了MultipartFile工具类,相关接口介绍如下
// MultipartFile工具类
package org.springframework.web.multipart;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import org.springframework.core.io.InputStreamSource;
import org.springframework.core.io.Resource;
import org.springframework.lang.Nullable;
import org.springframework.util.FileCopyUtils;
public interface MultipartFile extends InputStreamSource {
// 返回参数的名称
String getName();
//获取源文件的昵称
@Nullable
String getOriginalFilename();
// 返回文件的内容类型
@Nullable
String getContentType();
// 判断上传的文件是否为空
boolean isEmpty();
// 以字节为单位返回文件大小
long getSize();
/ 将文件内容转化成byte[] 并返回
byte[] getBytes() throws IOException;
//getInputStream() 返回InputStream读取文件的内容
InputStream getInputStream() throws IOException;
default Resource getResource() {
return new MultipartFileResource(this);
}
//transferTo是复制file文件到指定位置(比如D盘下的某个位置),不然程序执行完,文件就会消失,程序运行时,临时存储在temp这个文件夹中
void transferTo(File var1) throws IOException, IllegalStateException;
default void transferTo(Path dest) throws IOException, IllegalStateException {
FileCopyUtils.copy(this.getInputStream(), Files.newOutputStream(dest));
}
}
VUE文件
1. 配置文件
- vue.config.js
配置proxy代理解决跨域问题
// vue.config.js
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
transpileDependencies: true,
lintOnSave: false,//关闭语法检查
devServer: {
host: 'localhost',
port: 8888,
open: false,
proxy: {
'/api': {
target: 'http://localhost:8080',// 后台接口域名
ws: true,//如果要代理 websockets,配置这个参数
secure: false, // 如果是https接口,需要配置这个参数
changeOrigin: true,//是否跨域
pathRewrite: {
'^/api': ''
}
}
}
}
})
- main.js
引入axios,设置axiosdefault.baseURL为"/api",设置后方便proxy代理解析,本项目用于练习,将axios设置成了全局,实习开发中可根据项目需要灵活配置
引入axios之前需要先安装,安装后可import引入,安装命令如下
npm install axios
配置main.js文件
// main.js
import { createApp } from 'vue'
import App from './App.vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
import router from './router'
import store from './store'
// 引入axios
import axios from 'axios'
// 设置defaults.baseURL
axios.defaults.baseURL='/api'
const app = createApp(App)
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
app.component(key, component)
}
app.use(store).use(router).use(ElementPlus).mount('#app')
// 全局应用axios
app.config.globalProperties.$http = axios
配置好main.js和vue.config.js可创建组件实现文件上传,具体上传方式下面分为传统文件上传方式和el-upload方式进行详细介绍
1. Element Plus 的 el-upload 上传方式
el-upload文件上传相关配置可参考Element Plus官方文档
/uploadMultipleFile对应SpringBoot Controller当中的方法,需要在前面加上“api”以便于proxy解析代理
<script setup>
import {UploadFilled} from '@element-plus/icons-vue'
import {getCurrentInstance} from "vue";
const {proxy} = getCurrentInstance()
// 设置上传url
let fileUrl = "api/uploadMultipleFile"
function uploadFiles() {
proxy.$refs.upload.submit()
}
</script>
<template>
<h1>el-upload文件上传</h1>
<el-upload
ref="upload"
class="upload-demo"
drag
:action="fileUrl"
multiple
:auto-upload="false"
list-type="picture"
>
<el-icon class="el-icon--upload">
<upload-filled/>
</el-icon>
<div class="el-upload__text">
Drop file here or <em>click to upload</em>
</div>
<template #tip>
<div class="el-upload__tip">
jpg/png files with a size less than 500kb
</div>
</template>
</el-upload>
<el-button type="primary" @click="uploadFiles">上传</el-button>
</template>
2. 传统文件上传方式
在传统文件上传中介绍了“单文件上传”、“文件夹上传”和拖拽上传方式,下面分别采用了xhr方式和axios两种方式实现文件上传,代码如下
<script setup>
import {getCurrentInstance, reactive, ref} from "vue";
const {proxy} = getCurrentInstance()
const fd = new FormData();
const percentage = ref(0)
function onmouseover(e) {
// 阻止默认事件
e.preventDefault()
e.stopPropagation()
// 拖拽时禁用页面内容选取
document.onselectstart = function () {
return false
}
}
function dragenter(e) {
// 阻止默认事件
e.preventDefault()
e.stopPropagation()
}
function dragover(e) {
// 阻止默认事件
e.preventDefault()
e.stopPropagation()
// console.log(e)
}
/**
* 清除FormData
**/
function clearFormData(fd) {
fd.forEach(function (value, key) {
fd.delete(key);
})
}
/**
* 进度条颜色控制
**/
function customColorMethod(percentage) {
if (percentage < 30) {
return '#909399';
} else if (percentage < 70) {
return '#e6a23c';
} else {
return '#67c23a';
}
}
/**
* 进度条
**/
let onUploadProgress = (progressEvent) => {
const {loaded, total} = progressEvent;
let progress = Math.round((loaded / total) * 100)
percentage.value = progress
console.log(`Upload Progress: ${progress}%`);
}
function change(e) {
clearFormData(fd)
fd.append('file', e.target.files[0], e.target.files[0].name)
uploadFile(fd)
}
function uploadFile(fd) {
/**axios方式**/
proxy.$http.post("/uploadMultipleFile", fd, {
headers: {
'Content-Type': 'multipart/form-data',
}, onUploadProgress
}).then(data => {
if (data.status !== 200) proxy.$message.error(data.data)
proxy.$message.success(data.data)
})
/**xhr方式**/
/* // 1.创建xhr
var xhr = new XMLHttpRequest();
// 2.创建请求
let url = "api/uploadSingleFile"
xhr.open("POST", url);
// 3.发起请求
xhr.send(fd);
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
if (xhr.status === 200) {
// 上传成功
proxy.$message.success('上传成功')
} else {
// 上传失败
console.log('图片上传失败!' + xhr.responseText)
}
}
}*/
}
/**
* 拖拽方法
**/
function drop(e) {
e.preventDefault()
e.stopPropagation()
console.log(e)
clearFormData(fd)
for (let item of e.dataTransfer.items) {
const entry = item.webkitGetAsEntry()
upload(entry)
}
// proxy.$http.post("/uploadSingleFile", fd).then(data => {
// console.log(data)
// })
// 1.创建xhr
}
function upload_a() {
uploadFile(fd)
}
/**
* 判断是文件还是目录
**/
function upload(entry) {
if (entry.isDirectory) {
// 目录
const reader = entry.createReader()
reader.readEntries(entries => {
for (const entry of entries) {
upload(entry)
}
})
} else {
// 文件
entry.file(f => {
console.log('文件', f)
fd.append('file', f, f.name)
})
}
}
</script>
<template>
<h1>经典文件上传</h1>
<!-- 添加multiple属性实现多个文件上传-->
<input type="file" multiple @change="change">
<input type="file" webkitdirectory mozdirectory odirectory>
<div class="uploadArea" ref="dragArea" @dragenter="dragenter" @dragover="dragover"
@drop="drop" @change="change" @mouseover="onmouseover">
<UploadFilled class="icon"/>
<p style="color: #409EFF">文件拖拽上传区域</p>
</div>
<el-progress :text-inside="true" :stroke-width="24" :percentage="percentage" :color="customColorMethod"></el-progress>
<el-button type="primary" @click="upload_a">上传</el-button>
</template>
<style scoped>
.uploadArea {
color: #A8ABB2;
margin-top: 2%;
height: 200px;
background: #FAFAFA;
border: #DCDFE6 1px dashed;
border-radius: 20px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
box-sizing: border-box;
}
div .uploadArea:hover {
border: #409EFF 2px dashed;
}
p {
cursor: default;
}
.el-button {
margin-top: 2%;
}
.el-progress {
margin-top: 1%;
}
.icon {
width: 80px;
height: 80px;
//box-sizing: border-box;
}
</style>




vuejs/vue: 是一个用于构建用户界面的 JavaScript 框架,具有简洁的语法和丰富的组件库,可以用于开发单页面应用程序和多页面应用程序。
最近提交(Master分支:5 个月前 )
9e887079
[skip ci] 4 个月前
73486cb5
* chore: fix link broken
Signed-off-by: snoppy <michaleli@foxmail.com>
* Update packages/template-compiler/README.md [skip ci]
---------
Signed-off-by: snoppy <michaleli@foxmail.com>
Co-authored-by: Eduardo San Martin Morote <posva@users.noreply.github.com> 7 个月前
更多推荐
所有评论(0)