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 "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发布于博客园

 

posted @ 2024-04-22 14:14  快乐的总统95  阅读(885)  评论(0编辑  收藏  举报