At present in the component library on the desktop, drag the file upload basic is out of the box, there is not for everyone, but drag folder upload implementation is less, the reason was that the drag and drop to fils in the description of the folder, only within the folder information is not like use the input tag upload folder, Add all internal file information into a fileList, so special processing is required to bring the internal data.
Upload folders with input tags
<input
multiple="false"
type="file"
ref="folderUploader"
webkitdirectory
class="file-input"
@change="uploadHandler($event, 'folder')"
title="Files and folders cannot be uploaded at the same time. Only one folder can be uploaded at a time."
/>
Copy the code
UploadHandler gets the following message from an event:
Use drag and drop to upload folders
<! -- Container components -->
<FileDragWrap
v-show="!!!!! draggingStatus"
:draggingStatus="draggingStatus"
:uploadExts="uploadExts"
:uploadHint="uploadHint"
@change="(val) => (draggingStatus = val)"
@success="handleDragSuccess"
@error="handleDragError"
/>
Copy the code
<! FileDragWrap-->
<div
class="cme-drop-file-hint__wrap"
@dragover="handleDragWrapDragOver"
@drop="handleDragWrapDrop"
>
<div class="cme-drop-file-hint__icon">
<i class="icon-cme icon-cme-upload"></i>
</div>
<p class="cme-drop-file-hint__text">Release the mouse to upload files</p>
</div>
Copy the code
HandleDragWrapDrop event retrieves the following information:
We found that there was no description of the internal information of the folder, so we needed to use the unique method webkitGetAsEntry of Chrome to recursively get all the information and flatly convert it into a File object that can be uploaded.
/ * * *@description Drag event handling *@param Drag the event body */
async handleDragWrapDrop(event: DragEvent) {
const { dataTransfer } = event
if(! dataTransfer)return
const { files } = dataTransfer
// Check the type
const allowFile = find(files, (item) = > {
return some(this.uploadExts, (ext) = > {
return item.name.toLowerCase().endsWith(`.${ext.toLowerCase()}`) || item.type === ' '})})if (allowFile) {
if (files.length === 1) {
const { items, files } = dataTransfer
const item = items[0].webkitGetAsEntry()// Get the Entry of the current folder (webKit kernel specific), then recursively Entry
if (item) {
// It is a folder
if (item.isDirectory) {
const filesList: any[] = []
await this.scanFiles(item, filesList)
const copyEvent: any = { dataTransfer: { files: filesList } }
this.$emit('success', { event: copyEvent, msg: ' '.type: 'folder'})}else {
this.$emit('success', { event, msg: ' '.type: 'file'})}}}else {
this.$emit('success', { event: {}, msg: 'Single drag-and-drop only supports single file upload'}}})else {
this.$emit('error', { event: {}, msg: 'Upload file format error'}}})Copy the code
Scanning files recursively:
/ * * *@description Scan all folders and files in the folder and flatten the data into an uploadable File object *@param Item FileSystemDirectoryEntry Object instance (directory entity) */
scanFiles(entry: any, filesList: any[]) {
return new Promise((resolve, reject) = > {
if (entry.isDirectory) {
const directoryReader = entry.createReader()
directoryReader.readEntries(
async (entries: any[]) => {
entries.forEach(async (entry: any, index: number) => {
await this.scanFiles(entry, filesList)
if (index === entries.length - 1) {
resolve(1)}})},(e: any) = > {
reject(e)
}
)
} else {
entry.file(
async (file: any) => {
const path = entry.fullPath.substring(1)
/** Modifying webkitRelativePath is a core operation because the webkitRelativePath is empty in the drag event body, and webkitRelativePath is read-only. Normal assignments do not work. So this is the only way to assign entry. FullPath to webkitRelativePath**/
const newFile = Object.defineProperty(file, 'webkitRelativePath', {
value: path,
})
filesList.push(newFile)
resolve(1)},(e: any) = > {
reject(e)
}
)
}
})
}
Copy the code
Finally, we can upload the contents of the folder through the scanFiles method to the upload interface. Of course, the above components, files and folders are supported, I hope to help you ~