Stack Overflow Asked on December 30, 2021
I have the following dropzone where users can either select images or drag images into the dropzone.
When I select files through the input type=file
button and click the btnUpload
button, the images are uploaded. However, when I drag items into the dropzone and then click btnUpload
button, nothing happens: no logging, no network requests, nothing.
Why? Here’s my code.
<div id="drop-area">
<span id="status"></span>
<p>Drop files here</p>
<input type="file" id="fileElem" multiple accept="image/*" onchange="handleFiles(this.files)">
<label class="button" for="fileElem">Select files</label>
<progress id="progress-bar" max=100 value=0></progress>
<div id="gallery" /></div>
<input id="btnUpload" type="submit" class="button green small" value="Upload" />
<script type="text/javascript">
let btnUpload = document.getElementById("btnUpload")
btnUpload.addEventListener('click', uploadFiles, false)
function uploadFiles(event) {
event.preventDefault();
// TODO - validate file size, extension & amount
files = [...fileElem.files]
// Submit each file separately.
files.forEach(uploadFile)
//check if success and if so, remove from gallery
}
// This all copy & paste
// ************************ Drag and drop ***************** //
let dropArea = document.getElementById("drop-area")
// Prevent default drag behaviors
;['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
dropArea.addEventListener(eventName, preventDefaults, false)
document.body.addEventListener(eventName, preventDefaults, false)
})
// Highlight drop area when item is dragged over it
;['dragenter', 'dragover'].forEach(eventName => {
dropArea.addEventListener(eventName, highlight, false)
})
;['dragleave', 'drop'].forEach(eventName => {
dropArea.addEventListener(eventName, unhighlight, false)
})
// Handle dropped files
dropArea.addEventListener('drop', handleDrop, false)
function preventDefaults(e) {
e.preventDefault()
e.stopPropagation()
}
function highlight(e) {
dropArea.classList.add('highlight')
}
function unhighlight(e) {
dropArea.classList.remove('active')
}
function handleDrop(e) {
var dt = e.dataTransfer
var files = dt.files
handleFiles(files)
}
let uploadProgress = []
let progressBar = document.getElementById('progress-bar')
function initializeProgress(numFiles) {
progressBar.value = 0
uploadProgress = []
for (let i = numFiles; i > 0; i--) {
uploadProgress.push(0)
}
}
function updateProgress(fileNumber, percent) {
uploadProgress[fileNumber] = percent
let total = uploadProgress.reduce((tot, curr) => tot + curr, 0) / uploadProgress.length
//console.log('update', fileNumber, percent, total)
progressBar.value = total
return total === 100;
}
function handleFiles(files) {
files = [...files]
initializeProgress(files.length)
//files.forEach(uploadFile)
files.forEach(previewFile)
}
function previewFile(file) {
//console.error('file.name: ' + file.name);
let reader = new FileReader()
reader.readAsDataURL(file)
reader.onloadend = function () {
let img = document.createElement('img')
img.id = file.name;//.toString().replaceAll('"', '').replaceAll('.', '').replaceAll(' ', '_');
img.src = reader.result
document.getElementById('gallery').appendChild(img)
}
}
function uploadFile(file, i) {
var url = '/api2/uploadfile/135/3435' // TODO: change end point
var xhr = new XMLHttpRequest()
var formData = new FormData()
xhr.open('POST', url, true)
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest')
// Update progress (can be used to show progress indicator)
xhr.upload.addEventListener("progress", function (e) {
updateProgress(i, (e.loaded * 100.0 / e.total) || 100)
})
xhr.addEventListener('readystatechange', function (e) {
if (xhr.readyState == 4 && xhr.status == 200) {
if (updateProgress(i, 100)) {
//$("'" + "#gallery #" + xhr.responseText.replaceAll('"', '').replaceAll('.', '').replaceAll(' ', '_') + "'").remove();//how do we handle spaces in filenames?
//console.error(i);
$('#gallery img:nth-child(' + (i + 1) + ')').hide();
//alert('Complete') // TODO
return true;
}
}
else if (xhr.readyState == 4 && xhr.status != 200) {
$('#status').html(GetMessageStatus('Error: ' + xhr.responseText, 1));
return false;
}
})
formData.append('file', file)
xhr.send(formData)
}
</script>
UPDATE 1
I added my code here: https://plnkr.co/edit/HHPDL6Ndc6nxPMGn?open=lib%2Fscript.js
I debugged everything and the same path is executed. However, when I select 1 image via the button and hit upload button, in function uploadFiles, on this line files = [...fileElem.files]
the variable files
has length 1, but when I drag and drop the same image, and hit upload button the variable files
has length 0.
I think you need to managed the dropped images separately maybe in a array of dropped files because the files dropped in drop-area will not be considered in the File Upload html tag.
So you need to add a global variable to store dropped files array.
let droppedFiles = [];
Then in the handleDrop(e) method you need to add files in the droppedFiles array.
for (let i = 0; i < files.length; i++) {
droppedFiles.push(files[i]);
}
Now, at the submit/upload button you need to add this also, to make sure all files should get attached. (Files from file upload tag & dropped files).
for (let i = 0; i < droppedFiles.length; i++) {
files.push(droppedFiles[i]);
}
let droppedFiles = [];
let btnUpload = document.getElementById("btnUpload")
btnUpload.addEventListener('click', uploadFiles, false)
function uploadFiles(event) {
event.preventDefault();
// TODO - validate file size, extension & amount
files = [...fileElem.files];
for (let i = 0; i < droppedFiles.length; i++) {
files.push(droppedFiles[i]);
}
console.log(files.length);
// Submit each file separately.
//files.forEach(uploadFile)
//check if success and if so, remove from gallery
}
// This all copy & paste
// ************************ Drag and drop ***************** //
let dropArea = document.getElementById("drop-area")
// Prevent default drag behaviors
;['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
dropArea.addEventListener(eventName, preventDefaults, false)
document.body.addEventListener(eventName, preventDefaults, false)
})
// Highlight drop area when item is dragged over it
;['dragenter', 'dragover'].forEach(eventName => {
dropArea.addEventListener(eventName, highlight, false)
})
;['dragleave', 'drop'].forEach(eventName => {
dropArea.addEventListener(eventName, unhighlight, false)
})
// Handle dropped files
dropArea.addEventListener('drop', handleDrop, false)
function preventDefaults(e) {
e.preventDefault()
e.stopPropagation()
}
function highlight(e) {
dropArea.classList.add('highlight')
}
function unhighlight(e) {
dropArea.classList.remove('active')
}
function handleDrop(e) {
var dt = e.dataTransfer
var files = dt.files
for (let i = 0; i < files.length; i++) {
droppedFiles.push(files[i]);
}
handleFiles(files)
}
let uploadProgress = []
let progressBar = document.getElementById('progress-bar')
function initializeProgress(numFiles) {
progressBar.value = 0
uploadProgress = []
for (let i = numFiles; i > 0; i--) {
uploadProgress.push(0)
}
}
function updateProgress(fileNumber, percent) {
uploadProgress[fileNumber] = percent
let total = uploadProgress.reduce((tot, curr) => tot + curr, 0) / uploadProgress.length
//console.log('update', fileNumber, percent, total)
progressBar.value = total
return total === 100;
}
function handleFiles(files) {
files = [...files];
// fileElem= [...files];
initializeProgress(files.length)
//files.forEach(uploadFile)
files.forEach(previewFile)
}
function previewFile(file) {
//console.error('file.name: ' + file.name);
let reader = new FileReader()
reader.readAsDataURL(file)
reader.onloadend = function () {
let img = document.createElement('img')
img.id = file.name;//.toString().replaceAll('"', '').replaceAll('.', '').replaceAll(' ', '_');
img.src = reader.result
document.getElementById('gallery').appendChild(img)
}
}
function uploadFile(file, i) {
var url = '/api2/uploadfile/135/3435' // TODO: change end point
var xhr = new XMLHttpRequest()
var formData = new FormData()
xhr.open('POST', url, true)
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest')
// Update progress (can be used to show progress indicator)
xhr.upload.addEventListener("progress", function (e) {
updateProgress(i, (e.loaded * 100.0 / e.total) || 100)
})
xhr.addEventListener('readystatechange', function (e) {
if (xhr.readyState == 4 && xhr.status == 200) {
if (updateProgress(i, 100)) {
//$("'" + "#gallery #" + xhr.responseText.replaceAll('"', '').replaceAll('.', '').replaceAll(' ', '_') + "'").remove();//how do we handle spaces in filenames?
//console.error(i);
$('#gallery img:nth-child(' + (i + 1) + ')').hide();
//alert('Complete') // TODO
return true;
}
}
else if (xhr.readyState == 4 && xhr.status != 200) {
$('#status').html(GetMessageStatus('Error: ' + xhr.responseText, 1));
return false;
}
})
formData.append('file', file)
xhr.send(formData)
}
<div id="drop-area" style="border: 1px dashed">
<span id="status"></span>
<p>Drop files here</p>
<input type="file" id="fileElem" multiple accept="image/*" onchange="handleFiles(this.files)">
<label class="button" for="fileElem">Select files</label>
<progress id="progress-bar" max=100 value=0></progress>
<br />
<br />
</div>
<div id="gallery"></div>
<br />
<input id="btnUpload" type="submit" class="button green small" value="Upload" />
Answered by Mohan Rajput on December 30, 2021
Add fileElem.files = files
to the top of your handleFiles()
method, or modify your uploadFiles()
method. Currently, uploadFiles()
only pulls files from fileElem
. As a fix, you can set the fileElem
's file list to the dropped file in handleFiles()
. Thus, your new handleFiles()
method would look as follows:
function handleFiles(files) {
fileElem.files = files
files = [...files]
initializeProgress(files.length)
files.forEach(previewFile)
}
Answered by citysurrounded on December 30, 2021
Get help from others!
Recent Answers
Recent Questions
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP