Reputation: 35
My job is to make an HTML input where a user can select to upload "multiple things" at once, all are accepted, "multiple things" could be images with videos, or could be images with folders. or anything (literally).
The problem is, how? I've been thinking of a way of doing it, I've already read other questions on stackoverflow, I've read the question of the person who asked a similar question to mine, then folks replied to him to use JSzip. but.. I the answers are quite complicated, and are not directly answering my question, they're showing how to zip files on the front-end for the sake of downloading the zipped file. I don't want that. my goal is to zip the files on the front-end, and just hit the upload button, and on the server I'll have a zip file that I can extract and play with.
This is how I was thinking of how to do it and how it should.
just before I finish writing this question, here is an example, a user clicked on the file input on his browser and a window showed up asking him to select the stuff that he wants to upload click me to see the image the user now selected the following:
-── folder1
│ ├── myVideo1.mp4
│ └── myVideo2.mp4
├── folder2
│ ├── innerFolder
│ │ └── anything.gif
│ └── something.png
├── myImage1.jpeg
├── myImage2.jpeg
└── myImage3.jpeg
I need the exact same structure above, this is why I believe I should zip them (I believe I should, not 100% sure) because I need the folders too.
the user didn't compress anything and just selected the files and folders he wants, he hit the upload button, the browser compressed/tarballed/...or any term you want the selected stuff and POSTed the zip/(or whatever its) file to the server.
I can now extract everything from this file and safe them the way I want in the server.
I've taken a look at the
<input type="file" webkitdirectory mozdirectory />
but the problem with this is that I can't select files with folders at once, I'll have to select only folders. I don't want that.
probably the answer is with JSzip, but it doesn't seem that easy? I've tried to read their documentation and I couldn't understand anything there. I'm not 100% sure actually what is exactly JSzip and how it works. but you get the idea.
Upvotes: 0
Views: 2226
Reputation: 227310
You can take all the selected files/folders and add them to a ZIP file (using JSzip).
Using <input type="file" webkitdirectory>
and <input type="file" multiple>
, you can allow a user to select file(s) or a folder.
You need multiple elements, as you can either upload a file or a folder, but not both with one element. NOTE: You cannot have multiple
with webkitdirectory
(and yes webkitdirectory
works in Firefox, see: https://www.caniuse.com/mdn-api_htmlinputelement_webkitdirectory).
So, when a file/folder is selected you can add it to the ZIP file, then once everything you want is added, you can click a button to upload it.
Here's an example that lets you select files and folders to add to a zip. The "upload" button will just download the file as I cannot upload to your server from here. (NOTE: The saveAs()
function may not work in the example.)
let zip = new JSZip(),
// Used to show the file(s) selected
fileNames = document.getElementById('zipData');
Array.from(document.getElementsByClassName('upload')).forEach(u => {
u.addEventListener('change', e => {
let files = e.target.files;
for (let i = 0; i < files.length; i++) {
let file = files[i],
name = file.webkitRelativePath || file.name,
fileName = document.createElement('li');
// Append the name to the list
fileName.appendChild(document.createTextNode(name));
fileNames.appendChild(fileName);
// Add the file to the ZIP file
zip.file(name, file, {binary: true});
}
});
});
document.getElementById('zipUpload').addEventListener('submit', e => {
e.preventDefault();
// ZIP up all the files and get a blob
zip.generateAsync({type: "blob"}).then(blob => {
let ajax = new XMLHttpRequest(),
formData = new FormData();
// Add the blob to the data to be sent to the server
formData.append('zipFile', blob, Date.now() + '.zip');
ajax.upload.addEventListener('progress', function(e) {
let progress = Math.floor(e.loaded / e.total * 100);
console.log('Uploading: ' + progress + '%');
}, false);
ajax.addEventListener('load', function(e) {
if (ajax.readyState === 4 && ajax.status === 200) {
console.log('done.');
}
}, false);
ajax.open('POST', 'https://your.url', true);
// We can't actually upload from here, so just download it instead
//ajax.send(formData);
saveAs(blob, Date.now() + '.zip');
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.5.0/jszip.min.js" integrity="sha512-y3o0Z5TJF1UsKjs/jS2CDkeHN538bWsftxO9nctODL5W40nyXIbs0Pgyu7//icrQY9m6475gLaVr39i/uh/nLA==" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2.0.5/FileSaver.min.js" integrity="sha512-Qlv6VSKh1gDKGoJbnyA5RMXYcvnpIqhO++MhIM2fStMcGT9i2T//tSwYFlcyoRRDcDZ+TYHpH8azBBCyhpSeqw==" crossorigin="anonymous"></script>
<form id="zipUpload">
<input class="upload" type="file" multiple>
<input class="upload" type="file" webkitdirectory>
<button type="submit">
Upload your ZIP
</button>
</form>
<ul id="zipData"></ul>
Upvotes: 2