- What does not work when you drag drop?
- PHP receives no files?
- Or?
Help with drag and dropped file missing from request
I've been trying to make my own drag and drop file upload component and it works absolutely fine when I click to upload a file through the file select dialogue, but no luck with the drag and drop.
I've been using these articles as a guide: https://www.raymondcamden.com/2019/08/08/drag-and-drop-file-upload-in-vuejs https://dev.to/hundredrab/yet-another-vue-drag-and-drop-15m2
One thing is that if I log the file object to the console through either method, they're virtually the same so I'm not sure why the dropped file doesn't show up in the request.
<template>
<div v-cloak @drop.prevent @dragover.prevent>
<h1>Upload {{documentName}} <span>{{restriction}}</span></h1>
<div v-if="documentLocation">
<div>
<a :href="'/download/'+documentLocation">
<b>{{documentName}}</b> uploaded on {{documentUploadDate}}
</a>
<button @click="deleteDocument" type="button" role="button">
delete
</button>
</div>
</div>
<div v-if="file">
<div>
<div>
<b>{{ file.name }} ({{ formatBytes(file.size) }})</b>
<button @click="file = null">
remove
</button>
</div>
</div>
</div>
<div v-show="!file && documentLocation == null" @drop="dropFile">
<div>
<button type="button" @click="upload">
click here or drag and drop your file
</button>
<input type="file" :name="uploadName" :id="uploadName" style="display: none" @change="handleFile">
<input type="hidden" :name="'delete_'+uploadName" v-if="deleteToggle">
</div>
</div>
</div>
</template>
Script:
<script>
export default {
name: 'file-upload-bucket',
props: {
uploadName: { type: String, default: 'testUpload' },
documentName: { type: String, default: null },
documentLocationProp: { type: String, default: null },
documentUploadDate: {},
restriction: { type: String, default: null }
},
data() {
return {
file: null,
documentLocation: null,
deleteToggle: false,
}
},
mounted: function() {
if(this.documentLocationProp) {this.documentLocation = this.documentLocationProp;}
},
methods: {
upload() { document.getElementById(this.uploadName).click(); },
handleFile(e) {
let file = e.target.files[0];
if (!file) return;
this.file = file;
this.deleteToggle = false;
},
dropFile(e) {
let droppedFile = e.dataTransfer.files[0];
if (!droppedFile) return;
this.file = droppedFile;
this.deleteToggle = false;
},
formatBytes(a,b){if(0==a)return"0 Bytes";var c=1024,d=b||2,e=["Bytes","KB","MB","GB","TB","PB","EB","ZB","YB"],f=Math.floor(Math.log(a)/Math.log(c));return parseFloat((a/Math.pow(c,f)).toFixed(d))+" "+e[f]},
deleteDocument() {
if (window.confirm('Really delete '+this.documentName+'?')) { this.documentLocation = null; this.deleteToggle = true; }
}
},
}
</script>
Any help would be sincerely appreciated!
So, I solved my problem. in case anyone is searching for a similar solution. I set the ref on the input and pass $refs.file to my handleFile function. Then I modified dropFile to set this.$refs.file.files to e.dataTransfer.files, and pass that ref to handleFile, so I suppose that forces the dragged file to be interpreted by the DOM in the same way? I honestly don't understand, but this works.
Hope it helps someone!
<input type="file" :name="uploadName" :id="uploadName" style="display: none" ref="file" @change="handleFile($refs.file)">
handleFile(ref) {
let file = ref.files[0];
if (!file) return;
this.file = file;
this.deleteToggle = false;
},
dropFile(e) {
this.$refs.file.files = e.dataTransfer.files;
this.handleFile(this.$refs.file);
},
Please or to participate in this conversation.