"@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 "[email protected]" -F "[email protected];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發佈於博客園