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

{
    "description":"描述信息",
    "tags":[
        "標籤100",
        "標籤23"
    ]
}

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發佈於博客園

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章