Vue + SpringBoot:el-upload组件单文件、多文件上传实战解析
vue
vuejs/vue: 是一个用于构建用户界面的 JavaScript 框架,具有简洁的语法和丰富的组件库,可以用于开发单页面应用程序和多页面应用程序。
项目地址:https://gitcode.com/gh_mirrors/vu/vue
免费下载资源
·
单文件上传
后端
这个方法是用于处理HTTP POST
请求的,具体来说它处理的是上传 .dxf
文件的操作。下面是对该方法的详细解释:
方法参数
- @RequestParam:用于获取HTTP请求中的参数,这里是从请求中获取名为 “file” 的multipart类型文件。
- MultipartFile multipartFile:表示从客户端上传的文件,通常通过HTML表单或API调用发送。
方法逻辑
-
文件校验
- 检查文件是否为空。
- 检查文件大小是否超过50MB(52428800字节)。
- 如果文件为空或者过大,则返回一个失败的消息给客户端,错误代码为
BaseErrorCode.CLIENT_ERROR.code()
,并附带错误信息。
-
文件类型验证
- 获取文件原始名称
originalFilename
。 - 验证文件扩展名是否为
.dxf
,如果不是则返回一个失败的消息给客户端,错误信息为“只能导入dxf文件”。
- 获取文件原始名称
-
获取文件输入流
- 使用
getInputStream()
方法获取文件的输入流,这通常用于读取文件内容。
- 使用
-
返回结果
- 方法最后返回了一个
R.ok(resultMap)
,表示成功响应。
- 方法最后返回了一个
@PostMapping("/uploadDxfFile")
public R uploadDxfFile(@RequestParam(value = "file", required = true) MultipartFile multipartFile) throws Exception {
// 文件校验工作
if (multipartFile.isEmpty() || multipartFile.getSize() > 52428800) {
R.fail(BaseErrorCode.CLIENT_ERROR.code(), "上传文件不能为空,且不能大于50MB");
}
// 获取文件名
String originalFilename = multipartFile.getOriginalFilename();
if (!(originalFilename.endsWith(".dxf"))) {
return R.fail(BaseErrorCode.CLIENT_ERROR.code(), "只能导入dxf文件");
}
// 获取文件输入流
InputStream inputStream = multipartFile.getInputStream();
return R.ok(resultMap);
}
【R类】
package com.dam.common.core.domain;
import com.dam.common.constant.HttpStatus;
import java.io.Serializable;
/**
* 响应信息主体
*
* @author ruoyi
*/
public class R<T> implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 成功
*/
public static final int SUCCESS = HttpStatus.SUCCESS;
/**
* 失败
*/
public static final int FAIL = HttpStatus.ERROR;
private int code;
private String msg;
private T data;
public static <T> R<T> ok() {
return restResult(null, SUCCESS, "操作成功");
}
public static <T> R<T> ok(T data) {
return restResult(data, SUCCESS, "操作成功");
}
public static <T> R<T> ok(T data, String msg) {
return restResult(data, SUCCESS, msg);
}
public static <T> R<T> fail() {
return restResult(null, FAIL, "操作失败");
}
public static <T> R<T> fail(String msg) {
return restResult(null, FAIL, msg);
}
public static <T> R<T> fail(T data) {
return restResult(data, FAIL, "操作失败");
}
public static <T> R<T> fail(T data, String msg) {
return restResult(data, FAIL, msg);
}
public static <T> R<T> fail(int code, String msg) {
return restResult(null, code, msg);
}
private static <T> R<T> restResult(T data, int code, String msg) {
R<T> apiResult = new R<>();
apiResult.setCode(code);
apiResult.setData(data);
apiResult.setMsg(msg);
return apiResult;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public static <T> Boolean isError(R<T> ret) {
return !isSuccess(ret);
}
public static <T> Boolean isSuccess(R<T> ret) {
return R.SUCCESS == ret.getCode();
}
}
【HttpStatus类】
package com.dam.common.constant;
/**
* 返回状态码
*
* @author ruoyi
*/
public class HttpStatus
{
/**
* 操作成功
*/
public static final int SUCCESS = 200;
/**
* 对象创建成功
*/
public static final int CREATED = 201;
/**
* 请求已经被接受
*/
public static final int ACCEPTED = 202;
/**
* 操作已经执行成功,但是没有返回数据
*/
public static final int NO_CONTENT = 204;
/**
* 资源已被移除
*/
public static final int MOVED_PERM = 301;
/**
* 重定向
*/
public static final int SEE_OTHER = 303;
/**
* 资源没有被修改
*/
public static final int NOT_MODIFIED = 304;
/**
* 参数列表错误(缺少,格式不匹配)
*/
public static final int BAD_REQUEST = 400;
/**
* 未授权
*/
public static final int UNAUTHORIZED = 401;
/**
* 访问受限,授权过期
*/
public static final int FORBIDDEN = 403;
/**
* 资源,服务未找到
*/
public static final int NOT_FOUND = 404;
/**
* 不允许的http方法
*/
public static final int BAD_METHOD = 405;
/**
* 资源冲突,或者资源被锁
*/
public static final int CONFLICT = 409;
/**
* 不支持的数据,媒体类型
*/
public static final int UNSUPPORTED_TYPE = 415;
/**
* 系统内部错误
*/
public static final int ERROR = 500;
/**
* 接口未实现
*/
public static final int NOT_IMPLEMENTED = 501;
/**
* 系统警告消息
*/
public static final int WARN = 601;
}
前端
【组件】
<el-upload class="upload-demo" :action="uploadDxfAction" :data="uploadPostData"
:on-preview="handlePreview"
:on-remove="handleRemove" :before-remove="beforeRemove" :on-success="handleSuccess"
:headers="headers" :limit="1" :on-exceed="handleExceed" :file-list="fileList"
style=" width: 100%;">
<el-button size="mini" type="primary">上传dxf文件</el-button>
<div slot="tip" class="el-upload__tip" style="color: red;">
只能上传.dxf文件,且不超过50MB
</div>
</el-upload>
:action="uploadDxfAction"
:定义文件要上传到的后台接口地址:limit="1"
:限制只能上传一个文件:on-success="handleSuccess"
:定义文件上传成功时执行的方法:headers="headers"
:如果后台做了权限验证,需要在这里定义文件上传时的请求头’
【变量定义】
data() {
return {
// token
token: '',
// 请求头
headers: {},
passengerFlowImportDialogVisible: false,
// 文件上传地址(后端接受文件的地址)
uploadDxfAction: process.env.VUE_APP_BASE_API + "/packing/item/uploadDxfFile",
// 文件列表
fileList: [],
// 导入文件的同时向后台提交数据
uploadPostData: {},
/// 批量上传物品
uploadItemList: [],
// 设置所导入零件参数的时候,点击到的行
selectRow: {},
};
},
【方法定义】
handleSuccess(res) {
console.log("文件上传成功");
console.log("res:" + JSON.stringify(res.data.code));
// 这里可以定义一些文件上传成功之后的操作,例如成功提示、文件信息解析……
},
handleRemove(file, fileList) {
console.log(file, fileList);
},
handlePreview(file) {
console.log(file);
},
handleExceed(files, fileList) {
this.$message.warning(
`只能选择 1 个文件,如果想要更换文件,请删除原有文件`
);
},
beforeRemove(file, fileList) {
return this.$confirm(`确定移除 ${file.name}?`);
},
// 清除已经上传的文件
clearFileList() {
this.fileList = [];
},
handleChange(file, fileList) {
this.fileList = fileList;
},
多文件上传
后端
/**
* 导入一组dxf文件并完成解析
*
* @param multipartFiles 文件列表
* @param paramMap 额外参数映射
* @return 返回结果
* @throws Exception 异常
*/
@PreAuthorize("@ss.hasPermi('packing:item:uploadDxfFiles')")
@Log(title = "上传dxf文件组", businessType = BusinessType.IMPORT)
@PostMapping("/uploadBatchDxfFile")
public R uploadBatchDxfFile(@RequestParam(value = "files", required = true) List<MultipartFile> multipartFiles, @RequestParam(required = false) Map paramMap) throws Exception {
if (multipartFiles.isEmpty()) {
return R.fail(BaseErrorCode.CLIENT_ERROR.code(), "上传文件组不能为空");
}
// 解析出每个文件
List<Item> items = multipartFiles.stream()
.filter(file -> !file.isEmpty() && file.getSize() <= 52428800 && file.getOriginalFilename().endsWith(".dxf"))
.map(file -> {
try {
// 处理文件
} catch (Exception e) {
throw new RuntimeException("解析文件出错:" + file.getOriginalFilename(), e);
}
})
.collect(Collectors.toList());
if (items.isEmpty()) {
return R.fail(BaseErrorCode.CLIENT_ERROR.code(), "没有有效的dxf文件被上传");
}
HashMap<String, Object> resultMap = new HashMap<>();
resultMap.put("items", items);
return R.ok(resultMap);
}
前端
<el-upload ref="batchUpload" class="upload-demo" :action="uploadBatchDxfAction" :data="uploadPostData"
:on-preview="handlePreview"
:on-remove="handleRemove" :before-remove="beforeRemove" :on-success="handleBatchSuccess"
:headers="headers" multiple :on-exceed="handleExceed" :file-list="fileList"
:on-change="handleChange"
:auto-upload="false"
style="width: 100%;">
<el-button slot="trigger" size="small" type="primary">选取文件</el-button>
<el-button style="margin-left: 10px;" size="small" type="success" @click="submitBatchUpload">上传解析
</el-button>
<div slot="tip" class="el-upload__tip" style="color: red;">
只能上传.dxf文件,每个文件不超过50MB
</div>
</el-upload>
首先需要关闭自动上传:auto-upload="false"
,不然所选择的文件会被一个一个上传,我们希望同时将这些文件上传到服务器进行处理。
变量定义、方法定义和上面类似,这里只展示不一样的。在选取完文件之后,并不会自动上传到服务器,需要点击按钮手动上传,如果直接调用el-upload的提交方法,还是会一个一个文件的上传,因此我们需要自己写一个请求方法,我的请求方法如下:
import axios from 'axios'
// 批量上传文件
export function uploadBatchDxfFile(fileList, token) {
const formData = new FormData();
// 遍历文件列表,将每个文件添加到formData中
fileList.forEach((file, index) => {
// 你可以选择使用一个通用的键名(如'files'),并让后端处理多个同名的键值
// 或者为每个文件使用唯一的键名,这取决于你的后端需求
formData.append(`files`, file.raw, file.name); // 这里的`files`是后端期望的字段名
});
return axios.post(process.env.VUE_APP_BASE_API + '/packing/item/uploadBatchDxfFile', formData, {
headers: {
'Content-Type': 'multipart/form-data',
Authorization: `Bearer ${token}`
}
}).then(response => {
// 处理成功的响应
return response.data;
}).catch(error => {
// 处理错误情况
throw error;
});
}
注意需要给vue项目引入axios,才能使用上面的请求方法。最终在页面中给按钮触发事件绑定下面的方法即可
/**
* 将选中的文件批量上传
*/
submitBatchUpload() {
if (this.fileList.length === 0) {
this.$modal.msgWarning("请先选择文件再上传解析");
return;
}
uploadBatchDxfFile(this.fileList, this.token).then(res => {
})
},
GitHub 加速计划 / vu / vue
80
16
下载
vuejs/vue: 是一个用于构建用户界面的 JavaScript 框架,具有简洁的语法和丰富的组件库,可以用于开发单页面应用程序和多页面应用程序。
最近提交(Master分支: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> 6 个月前
e428d891
Updated Browser Compatibility reference. The previous currently returns HTTP 404. 6 个月前
更多推荐
已为社区贡献7条内容
所有评论(0)