YaYa
YaYa

Reputation: 35

zip/compress/tarballing or whatever it's called files on the front-end (browser)

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

The end of the question,


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

Answers (1)

gen_Eric
gen_Eric

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

Related Questions