File upload for actual combat of front-end SPA project based on Vue and Quasar (10)
review
Through the previous article based on Vue and Quasar front-end SPA project actual combat data import (9) introduced, realize the business data batch import function, this article mainly introduces file upload related content.
Introduction
Crudapi supports attachment fields, and the file url string is stored in the table field. Attachments can be uploaded through other file management systems such as Alibaba Cloud's OSS, or using the file management API that comes with the system, including ordinary file upload and large file slice upload.
UI interface
File Upload
Large file upload
API
File upload API includes two functions: normal file upload and large file slicing, which can be viewed through swagger documents. Encapsulate the api with axios, the name is file
import { axiosInstance } from "boot/axios";
const HEADERS = {
"Content-Type": "multipart/form-data"
};
const file = {
upload: async function(data, progressCallback) {
console.log("file->upload")
return axiosInstance.post(`/api/file` , data,
{
headers: HEADERS,
onUploadProgress: (progressEvent) => {
if (progressCallback) {
progressCallback(progressEvent)
}
}
});
},
bigUpload: async function(data, progressCallback) {
console.log("file->bigUpload")
return axiosInstance.post(`/api/file/big` , data,
{
headers: HEADERS,
onUploadProgress: (progressEvent) => {
if (progressCallback) {
progressCallback(progressEvent)
}
}
});
}
};
export { file };
Core code
CFile component
<q-toggle v-model="enableBigFile" label="开启大文件上传模式" />
<div v-show="!enableBigFile" class="q-py-md">
<q-file v-model="normalFile" label="请选择文件(普通上传)">
<template v-slot:prepend>
<q-icon name="attach_file" />
</template>
<template v-slot:after>
<q-btn round dense flat icon="send" @click="onSubmitClick" />
</template>
</q-file>
</div>
<div v-show="enableBigFile" class="q-py-md">
<q-file v-model="bigFile" @input="bigFileAdded" label="请选择文件(大文件上传)">
<template v-slot:prepend>
<q-icon name="attach_file" />
</template>
<template v-slot:after>
<q-btn round dense flat icon="flight_land" @click="onBigSubmitClick" />
</template>
</q-file>
</div>
Use toggle to switch the upload mode, if it is a small file, use the normal method.
Normal upload
async onSubmitClick() {
console.info("CFile->onSubmitClick");
if (!this.normalFile) {
this.$q.notify({
message: '请选择文件!',
type: 'warning'
});
return;
}
this.$q.loading.show({
message: "上传中"
});
try {
let form = new FormData()
form.append('file', this.normalFile);
this.fileInfo = await fileService.upload(form, (e)=> {
console.info(e);
});
this.$q.loading.hide();
this.$emit("input", this.fileInfo);
} catch (error) {
this.$q.loading.hide();
console.error(error);
}
}
Large file slice upload
bigFileAdded(f) {
console.info("CFile->fileAdded");
if (!f) {
console.info("CFile->cancel");
return;
}
this.$q.loading.show({
message: "文件准备中"
});
FileMd5(f, this.chunkSize, (e, md5) => {
this.md5 = md5;
console.info(e);
console.info(md5);
this.$q.loading.hide();
});
},
async onBigSubmitClick() {
console.info("CFile->onBigSubmitClick");
if (!this.bigFile) {
this.$q.notify({
message: '请选择文件!',
type: 'warning'
});
return;
}
this.$q.loading.show({
message: "上传中"
});
try {
let chunks = this.getChunks();
let reqs = [];
for (let i = 0; i < chunks; ++i) {
reqs.push(this.uploadWithBlock(i));
}
await Promise.all(reqs)
.then((datas) => {
console.info(datas);
this.checkFinished(datas);
});
} catch (error) {
this.$q.loading.hide();
console.error(error);
}
}
If a large file is uploaded in a common way, the speed may be slow and unstable due to network reasons, so the slice method is used for multi-threaded upload. The specific principle is as follows: first calculate the MD5 of the file, the background will only determine the same file according to the MD5, and different blocks of the same file will be written in the corresponding position of the same file according to the size and offset. When the last block is uploaded successfully, it means The upload is over. The default fragment size is 20MB, which can be configured to the required value. The front-end can realize simultaneous upload by multiple threads through the ajax call method of Promise.all.
File table as an example
The "Link" field of the file table is set to "Attachment ATTACHMENT", and the CFile component will be automatically used on the page to add business data.
After selecting a large file, click the upload icon, and through the chrome network request, it is found that the multi-threaded upload mode has been activated, and the download can be viewed after the upload is complete.
summary
This article mainly introduces the file upload function, including the normal upload mode and the large file slice upload mode. After the large file slice upload mode is optimized, it is easy to support the resumable upload and the second upload. The file upload function will be optimized according to the needs in the future.
demo
Official website address: https://crudapi.cn
Test address: https://demo.crudapi.cn/crudapi/login
Attached source code address
GitHub address
https://github.com/crudapi/crudapi-admin-web
Gitee address
https://gitee.com/crudapi/crudapi-admin-web
Due to network reasons, GitHub may be slow, just change to visit Gitee, and the code will be updated synchronously.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。