vue.js 3 上传文件:el-upload 组件
"@element-plus/icons-vue": "^2.3.1",
"axios": "^1.6.8",
"element-plus": "^2.6.2",
"pinia": "^2.1.7",
"pinia-plugin-persistedstate": "^3.2.1",
"vue": "^3.4.21",
"vue-router": "^4.3.0"
---
序章
vue.js 3.0 + Element Plus 的 <el-upload> 组件进行文件上传。
gitee.io 的 上传组件 介绍:
https://element-plus.gitee.io/en-US/component/upload.html
需求
上传1个文件,同时,上传文件的一些信息。
解决
后端
spring boot 开发的接口:
// MediaType.MULTIPART_FORM_DATA_VALUE = "multipart/form-data"
// @RequestPart
// file 必须
// dto 非必须
@PostMapping(value = "file/upload/to/{folderUuid}", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public ResultVO<UploadFileVO> uploadFile(@AuthenticationPrincipal AppUserDetails appUserDetails,
@PathVariable String folderUuid,
@RequestPart("file") MultipartFile file,
@RequestPart(value = "dto", required = false) @Validated UploadFileDTO dto) {
return fileService.uploadFileToFolder(appUserDetails, folderUuid, file, dto);
}
curl 接口调试
上传文件 dev.html。
准备 dto文件:testdto.json { |
curl 命令: curl -v -X POST http://localhost/file/upload/to/7a969e2119e9f6aed6206c909780c734 -F "file=@dev.html" -F "dto=@testdto.json;type=application/json" -H "Cookie: JSESSIONID=4269DE7ADD840D1E4A7D7188F267B789" |
前端
使用 <el-upload> 组件选择文件:ben发布于博客园
- 单个文件
- 选择文件后不立即上传
- 选择后点击按钮再执行上传
代码:<script setup>
<script setup>
// 关键的 上传部分
function onUploadFilesToFolder() {
if (isNullOrUndefined(addFileFormDto.files)) {
ElMessage.warning('没有文件要上传')
return
}
let fileNum = addFileFormDto.files.length
// 逐个上传
for (let i=0; i<fileNum; i++) {
httpPostUploadFile(addFileFormDto.files[0]);
}
}
function httpPostUploadFile(fileObj) {
let fileName = fileObj.name
let formData = new FormData()
// file
// .raw 不可少!
formData.append('file', fileObj.raw, fileName)
// dto
let dto = {}
dto.description = addFileFormDto.description
dto.tags = []
// 列表操作:清空 参数1,再把 参数2 的元素放入 参数1
fillListAfterClear(dto.tags, addFileFormDto.tags)
// 包装成 Blob 对象
// let dtoBlob = new Blob([dto], { type: 'application/json' }) // 错误方式,发生异常
let dtoBlob = new Blob([
JSON.stringify(dto)
], { type: 'application/json' }) // 正确方式
formData.append('dto', dtoBlob)
let folderUuid = gprops.folder.uuid
let method = "post"
let url = fileMgntUrls.file.upload
url = url.replace('{folderUuid}', folderUuid)
let headers = {
'content-type': 'multipart/form-data'
};
axios({
method,
url,
data: formData,
headers
})
.then(response => {
let result = response.data
if (isNullOrUndefined(result)) {
ElMessage.error('上传文件失败:null')
return
}
if (! isCodeOk(result.code)) {
ElMessage.error('上传文件失败:' + JSON.stringify(result))
return
}
ElMessage.success('上传文件成功:' + fileName)
needUpdate.value++
clearUploadData()
})
.catch(e => {
console.error('上传文件失败:')
console.error(e)
ElMessage.error('上传文件失败:' + fileName + ", error=" + error.message)
})
}
</script>
代码:<template>
<template>
<el-upload
v-model:file-list="addFileFormDto.files"
:multiple="false"
:limit="1"
:drag="true"
:auto-upload="false"
>
<template #trigger>
<el-button type="primary">选择文件</el-button>
</template>
<template #tip>
1、一次添加1个文件。2、单个文件最大 20MB 字节。
</template>
<el-button type="primary" @click="onUploadFilesToFolder">上传</el-button>
</el-upload>
</template>
结果:上传成功。ben发布于博客园
知识点
1、FormData 对象
https://developer.mozilla.org/en-US/docs/Web/API/FormData
append方法:
https://developer.mozilla.org/en-US/docs/Web/API/FormData/append
方法签名(详情见文档):
append(name, value) append(name, value, filename) |
2、Blob 对象
https://developer.mozilla.org/en-US/docs/Web/API/Blob
组装 json 为 Blob:
const obj = { hello: "world" }; const blob = new Blob([JSON.stringify(obj, null, 2)], { type: "application/json", }); |
3、JSON.stringify 方法 3参数?
4、多个文件上传
按照上面的代码(逐个上传),可能会导致错误——异步、同步 问题。
或许(TODO),加入 async/await 可以解决,暂未试验。
---END---
本文链接:
https://www.cnblogs.com/luo630/p/18150480
ben发布于博客园
参考资料
1、
ben发布于博客园
ben发布于博客园