The company needs to develop a management system that includes a file management module. File module mainly contains the company’s various departments file classification and file allocation permissions. During file uploading, large files must be uploaded to prevent network timeout failure, which involves file fragment uploading.
The effect
Plupload has the following functions and features:
- There are multiple upload methods: HTML5, Flash, Silverlight, and traditional. Plupload will automatically detect the current environment and select the most suitable upload method, and will use HTML5 method in preference. So you don’t have to worry about which upload methods your current browser supports, Plupload will automatically choose the most suitable one for you.
- Supports drag and drop to select files to be uploaded.
- Image compression is supported in the front end, that is, image files are compressed before they are uploaded.
- Native file data can be read directly, which has the advantage of displaying image files on the page for preview before they are uploaded, for example.
- Support for uploading large files into small pieces, because some browsers cannot upload large files, such as several gigabytes of files.
Plupload Procedure
- NPM install –save plupload
- Instantiate a plupload object and pass in a configuration parameter object for the various configurations.
- Call the init() method of the plupload instance object for initialization.
- Register all the events you need on your Plupload instance object. Plupload Many events will be triggered during the process from selecting a file to uploading a file. We can use these events to interact with plupload.
The documentation recommends this (explained in detail)www.cnblogs.com/2050/p/3913…
The specific implementation
Spark-md5 is used to obtain the MD5 of the file
- Install NPM install –save plupload and NPM install –save spark-MD5
- Introduction: In the page into the import plupload from ‘plupload/js/plupload. Full. Min. Js’ and import FileMd5 the from ‘@/utils/file-md5.js’
- Since the parameters have been passed to the back end in the form of a form, you can use the QS library to achieve.
The relevant code
Select box code (support drag and drop related API to see documentation)
The view layer
<el-row type="flex">
<el-tooltip class="item" effect="dark" :content="' Support extension: ${acceptFiles} '" placement="bottom-start">
<el-button id="browseButton" type="primary" icon="el-icon-upload2">Please select file</el-button>
</el-tooltip>
<span class="tip-txt">Or drag the file to the lower box</span>
</el-row>
Copy the code
Variables defined in data
acceptFiles:'.txt,.png,.jpg,jpeg,.mp3,.mp4,.doc,.docx,.xls,.xlsx,.ppt,.pdf,.rar,.zip'.limit:20.// Maximum number of uploads
fileRawList: [].// The plug-in returns a list of files to select
Copy the code
Plupload initialization and related configuration code
Process and Ideas
- Variables that require instance Settings can be modified by calling setOption.
- Tip: Remember to call instance splice (instance, instance, instance…..) to remove the specified file. .
- The logic in it needs to be communicated with the back end, what that step needs to do, what data needs to be passed.
- The process is to select the file.
- Get the MD5 of the file and call the interface to initialize the file to get the file_id returned by the back end and append it to the current file object.
- The user clicks upload, and when you have configured some parameters of the plug-in, it is actually up to the plug-in to upload.
- There is a callback for every file that has been successfully uploaded, and the backend interface needs to be called to tell the backend that those files have been uploaded and need to be merged. That’s the whole process
pluploadInit() {
var that = this
var uploader = new plupload.Uploader({
browse_button: 'browseButton'.url: ' '.// Dynamically configure in the BeforeUpload method
chunk_size: '1MB'.// Set the size of a slice in file-MD5 to 1, 1MB =1048576b, better set a fixed 1MB, do not change
headers: that.headers,
multipart: true.// Multipart /form-data will be used when true
max_retries: 1.// Number of retries when plupload.HTTP_ERROR occurs. If the value is 0, no retries will be performed
drop_element:'drop_id'.headers: {'Authorization':'Bearer '+localStorage.getItem("pass_neutral_access_token")},filters: {
mime_types: [{extensions: that.acceptFiles.replace(/\./g.' ')},prevent_duplicates: true.// Duplicate files cannot be selected
max_file_size: '1024mb' // Maximum file that can be uploaded
},
init: {
BeforeUpload(up, file) {
// Reset the upload path. The back end requires the file ID to be spelled on the path
up.setOption('url'.`${baseUrl['defaultBaseUrl']}file/upload/${file.file_id}`)
// Additional parameters for upload, custom parameters, as key/value pairs
up.setOption('multipart_params', {
'size': file.size,
'md5': file.md5,
type:2})},FileFiltered(up, files) {
console.log('FileFiltered', up, files)
},
FilesAdded(up, files) {
// console.warn("11",files)
// Add files and limit the number of files
// To remove files, you must call the instance splice to remove some files, otherwise the file will not be selected the second time
if(that.limit > that.fileRawList.length){
// Whether the selected file exceeds the limit
if(files.length>that.limit){
up.splice(that.limit,files.length-that.limit)// Remove the excess} that.fileRawList.push(... files.slice(0,that.limit - that.fileRawList.length))// Add as many as you need
files = that.fileRawList
}else{
that.$message({
message: 'You can choose at most${that.limit}A file `.type: 'error'
});
up.splice(0,files.length)// Remove all of them
return
}
// The following operations are asynchronous, and each step needs to be completed before the next step can be executed, so use promise.all
let queueList = []// The file will be processed after the request is traversed
let md5Queue = []/ / the md5 queue
files.forEach(async (f) => {
// Add an MD5 queue
md5Queue.push(
new Promise((res,rej) = >{
f.status = -1
FileMd5(f.getNative(), (e, md5) = > {
f['md5'] = md5
f.status = 1
// Wait for the resolution to succeed before processing the promise state
res()
})
})
)
})
// Wait for the md5 queue to complete
Promise.all(md5Queue).then(() = >{
files.map(async (item)=>{
// Add a queue
queueList.push(
new Promise((resole,reject) = >{
that.fetch('File initialization interface, where the back end will return file_id', {headers: {'Content-Type':'application/x-www-form-urlencoded'
},
data:qs.stringify(
{
dirId:that.currentFolderObj.file_id,
name:item.name,
size:item.size,
md5:item.md5,
chunks:Math.ceil(item.size / 1048576),
}
)
}).then(res= >{
resole()
item['file_id'] = res.file_id// Object modification}})})))// After all files have successfully initialized the promise, proceed to the next step
Promise.all(queueList).then(() = >{
// The file upload button is displayed here})})},FilesRemoved(upp, files){},ChunkUploaded(uploader,file,responseObject){},FileUploaded(up, file, info) {
let res = JSON.parse(info.response)
if (res.code === 1) {
/** FETCH is an encapsulated network request tool. When a file is cut into 5 pieces and all 5 pieces have been uploaded successfully, the fetch is called back to this place. The backend needs to be told which files have been uploaded successfully, and the backend can merge these files */
that.fetch('Switch to your interface', {method:'put'.headers: {'Content-Type':'application/x-www-form-urlencoded'
},
data:qs.stringify(
{
fileId:file.file_id
}
)
})
that.up.refresh()
}
},
UploadComplete(up, files){},Error(up, args) {
console.warn("Error message",args)
if(args.code == -600){
that.$message({
type:'error'.message:'File contents cannot be empty'
})
}
}
}
})
uploader.init()
this.up = uploader
},
Copy the code
Towards the end of the project, I used transition to give the user some better interaction. I added some animations for the recycle bin and file switching.
This is basically the end of the module, but it is possible to add the ability to pause and continue files in the future
/utils/file-md5.js file code
'use strict'
import SparkMD5 from 'spark-md5'
export default function(file, callback) {
var blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice
var chunkSize = 1048576 // Read in chunks of 1MB
var chunks = Math.ceil(file.size / chunkSize)
var currentChunk = 0
var spark = new SparkMD5.ArrayBuffer()
var fileReader = new FileReader()
fileReader.onload = function(e) {
// console.log('read chunk nr', currentChunk + 1, 'of', chunks)
spark.append(e.target.result) // Append array buffer
currentChunk++
if (currentChunk < chunks) {
loadNext()
} else {
callback(null, spark.end())
// console.log('finished loading')
}
}
fileReader.onerror = function() {
callback('oops, something went wrong.')}function loadNext() {
var start = currentChunk * chunkSize
var end = ((start + chunkSize) >= file.size) ? file.size : start + chunkSize
fileReader.readAsArrayBuffer(blobSlice.call(file, start, end))
}
loadNext()
}
Copy the code