5

I want to receive a zip file as a string from an Ajax request and then hold it in memory so it can be downloaded multiple times if necessary so that only the one request is sent.

I tried to download it with this:

zip_string = 'PK etc.'

function download(filename, text) {
  var element = document.createElement('a');
  element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text));
  element.setAttribute('download', filename);

  element.style.display = 'none';
  document.body.appendChild(element);

  element.click();

  document.body.removeChild(element);
}

// Start file download.
download("zip1.zip", zip_string);

It came through as a zip but then there was obviously a problem because it wouldn't open. Can anyone see what I'm doing wrong?

1
  • You should create a blob url instead of creating a base64 str, using URL.createObjectURL(blob) Commented Aug 9, 2018 at 5:30

3 Answers 3

10

I solved the problem by encoding the zip file string as base64 on the server before it gets sent through.

with open(file, "rb") as f:
    bytes = f.read()
    encoded = base64.b64encode(bytes)

And then in the JS I just specify that it's base64:

zip_string = 'UEsDBBQAAAAIANQzCU0J56mLPAIAAD4VAAAOAAAA etc.'

function download(filename, data) {
  var element = document.createElement('a');
  element.setAttribute('href', 'data:text/plain;base64,' + data);
  element.setAttribute('download', filename);

  element.style.display = 'none';
  document.body.appendChild(element);

  element.click();

  document.body.removeChild(element);
}

// Start file download.
download("zip1.zip", zip_string);
Sign up to request clarification or add additional context in comments.

1 Comment

I wonder if there's a way to download the zip without base64 encoding it. By specifying the correct Blob type?
3

Using JSZip package: https://stuk.github.io/jszip/

public async downloadFile(filename: string, content: string) {
        const zip = new JSZip();
        await zip.loadAsync(content, {base64: true});
        const blob = await zip.generateAsync({type:"blob"});

        const element = document.createElement("a");
        element.setAttribute("href", window.URL.createObjectURL(blob));
        element.setAttribute("download", filename);
        element.style.display = "none";
        document.body.appendChild(element);
        element.click();
        document.body.removeChild(element);
    }


const fileName = "test.zip";
const content = "UEsDBAoAAAAAAI5ONE9i6ZVwCQAAAAkAAAAIAAAAdGVzdC50eHRUZXN0IGZpbGVQSwECPwAKAAAAAACOTjRPYumVcAkAAAAJAAAACAAkAAAAAAAAACAAAAAAAAAAdGVzdC50eHQKACAAAAAAAAEAGABz76T2f2/VAXPvpPZ/b9UB1NBncjhp1QFQSwUGAAAAAAEAAQBaAAAALwAAAAAA"; // base64 content without mimeType

this.downloadFile(fileName, content);

1 Comment

This is an amazing library!
1

The data type of your link's href is plain text (ie as specified by data:text/plain) which basically means, the contents of the link will be treated by the browser as plain text.

A zip archive is a binary format - you will need to do a bit more work to generate a real zip file and then cache it client side, in this way. You may want to look at zip.js as a library to help you with this.

You can however make a simple change to get the download function working - just change "zip1.zip" to "zip1.txt". I've prepared a jsFiddle here if you to see this in action.

Hope that helps!

1 Comment

Thanks, but I want an actual .zip file to be downloadable, not a .txt file

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.