1. What is shard upload
Cut a file into a series of data fragments of specific sizes and upload these data fragments to the server separately;
After all uploads are completed, the server will merge these data fragments into a complete resource;
During the upload process, the upload is interrupted due to external factors (such as network fluctuations), and the upload progress of the file will be retained the next time it is uploaded (renewal point transmission);
2. Upload component templates
Contains three parts:
- Upload components, use el-upload
- Progress bar component, using el-progress
- Upload the complete status component, customize it using el-input
<el-form-item label="Upload attachment" prop="uploadFile"> <el-upload v-if="!" class="upload-demo" drag :show-file-list="false" :action="APP_MANAGEMENT.uploadFile" // Pass parameters according to the project's interface :data="{ applicationId: applicationId, applicationVersion: applicationVersion, bucketName: 'app' }" // Override the default http request :http-request="handleFileUpload" > <el-icon class="el-icon--upload"> <upload-filled /> </el-icon> <div v-if="!progress" class="el-upload__text"> Drop file here or <em>click to upload</em> </div> // Progress bar <el-progress v-else :text-inside="true" :stroke-width="24" :percentage="progress" status="success" /> </el-upload> // Hide the upload file component after successful upload <div v-else style="display: flex;"> <el-input v-model="" readonly> </el-input> <div style="display: flex;"> <el-button type="primary" :icon="Download" size="small" @click="handleFileDownload" /> <el-button type="primary" :icon="Delete" size="small" @click="handleFileDel" /> </div> </div> </el-form-item>
3. Upload component logic
3.1 Basic ideas
Use el-upload to select a file
Select the successful callback function. You can read file information and use it to verify the legality of the file in the front-end.
After the front-end verification file is legal, slice the file
passRequest pollingPass the slice to the backend
3.2 Select Upload File
In this step, file information can be obtained
Verify the legality of the file based on the file information
After the verification is successful, call the file slice method
/** * @description: Select upload file * @param file el-upload parameter returned */ const handleFileUpload = async (file: any) => { ('el-upload Returned parameters === ', ); // If the file is legal, then upload it in pieces if (await checkMirrorFile(file)) { // File information const files = ; // Slices starting from 0 const shardIndex = 0; // Call file slicing method uploadFileSilce(files, shardIndex); // If the file is illegal, then prompt } else { ('Please check whether the file is legal! '); } };
3.3 Verify whether the file is legal
Verify file format
Verify file size
Call the interface to verify the remaining space of the disk
/** * @description: Verify file legality */ const checkMirrorFile = async (file) => { // Verify file format, support .zip/.tar const fileType = ('.') if (fileType[ - 1] !== 'zip' && fileType[ - 1] !== 'tar') { ('File format is wrong, only .zip/.tar') return false } // Verify file size const fileSize = ; // Is the file size exceeding 2G if (fileSize > 2 * 1024 * 1024 * 1024) { ('Upload file size cannot exceed 2G') return false } // Call the interface to verify the file legality, such as determining whether the disk space is sufficient const res = await checkMirrorFileApi() if ( !== 200) { ('Cannot view the available space of the disk for the time being, please try again') return false } // Check the disk capacity if ( && > 0) { let saveSize = 0 (i => { // Disk space assignment if ( === '/dev/mapper/centos-root') { // The return value is GB, converted to byte B saveSize = * 1024 * 1024 * 1024 } }) // The uploaded file size does not exceed the available space of the disk if (fileSize < saveSize) { return true } else { ('File size exceeds the available space capacity of disk') return false } } else { ('File size exceeds the available space capacity of disk') return false } }
3.4 File encryption
File upload here is encrypted with MD5, and it requires installation dependencies spark-md5
npm i spark-md5
/** * @description: File encryption processing */ const getMD5 = (file: any): Promise<string> => new Promise((resolve, reject) => { const spark = new (); // Get file binary data const fileReader = new FileReader(); (file); // file is the obtained file // Execute functions asynchronously ('load', (e: any) => { (); const md5: string = (); resolve(md5); }); ('error', (e) => { reject(e); }); });
3.5 Merge files
The parameters required by the interface are:
- file name
- File unique hash value
After the interface merge is completed, the front-end displays the uploaded file name
/** * @description: Merge files * @param name File name * @param hash file unique hash value * @return Name */ const composeFile = async (name: string, hash: string) => { ('Start file merging'); const res = await uploadFileMerge({ applicationId: , applicationVersion: , bucketName: 'app', fileName: name, hash, }); ('Backend interface merge files ===', res); if ( === 200 && ) { // After the merge is successful, adjust the uploaded file name = name; } };
3.6 File slice upload
Interface polling - carry one file slice to the backend at a time; after the backend receives the slice and returns the successful status code, the next slice upload is performed
/** * @description: Sharding function * @param file * @param shardIndex Number of shards */ const uploadFileSilce = async (file: File, shardIndex: number) => { // file name const { name } = file; // File size const { size } = file; // Size const shardSize = 1024 * 1024 * 5; // File encryption const hash: string = await getMD5(file); // Total number of shards const shardTotal = (size / shardSize); // If the current shard index is greater than the total shard count if (shardIndex >= shardTotal) { = false; = 100; // Merge files composeFile(name, hash); return; } // Where the file starts and ends const start = shardIndex * shardSize; const end = (start + shardSize, size); // Start cutting const packet = (start, end); // Splicing request parameters const formData = new FormData(); ('file', packet); ('applicationId', ); ('applicationVersion', ); ('bucketName', 'app'); ('hash', hash); ('shardSize', shardSize as unknown as string); ('seq', shardIndex as unknown as string); // If the current shard index is less than the total shard count if (shardIndex < shardTotal) { // The progress bar retains two decimal places to display = Number(((shardIndex / shardTotal) * 100).toFixed(2)) * 1; // Call the file upload interface const res = await uploadFile(formData); if ( !== 200) { ('Upload failed'); = 0; return; } if ( === 200 && === 200) { // Here are the operations performed after all slices are uploaded successfully ('Uploaded successfully'); } // eslint-disable-next-line no-param-reassign shardIndex++; // Recursively call sharding function uploadFileSilce(file, shardIndex); } };
4. Reference article
4.1 Article link
Upload and download of front-end large files (slice upload)
4.2 Notes mentioned in reference to the article
4.2.1 nginx upload size limit
The default upload size of nginx is 1MB. If it exceeds 1MB, you need to modify the nginx configuration to lift the upload limit.
4.2.2 Large file download
/** * @description: Dynamically create a tag to realize large file download */ const downloadMirror = async (item) => { let t = { id: , } const res = await downloadMirrorApi(t) if (["content-disposition"]) { let temp = ["content-disposition"].split(";")[1].split("filename=")[1] let fileName = decodeURIComponent(temp) //Realize file download by creating a tag let link = ('a') = fileName = 'none' = (link) () (link) } else { ElMessage({ message: 'This file does not exist', type: 'warning', }) } }
Summarize
This is the article about using Vue3+ElementPlus front-end to realize shard upload. For more related content on Vue3+ElementPlus front-end shard upload, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!