Analysis of Multi file Download Method Based on JavaScript

  • 2021-08-06 20:04:18
  • OfStack

Downloading files can be said to be a common topic with 10 points, and many front-end projects will have such requirements, such as exporting highChart statistical charts, saving pictures in online picture editing, exporting codes in online code editing, and so on. Most of the time, we only give one link. Users need to right-click on the link and select "Save As". Although this process is not troublesome, it still needs two steps. If users want to save multiple link files in the page, they have to repeat the operation many times. The most common one is the audio download on English listening websites, and their hands are numb!

The purpose of this article is to introduce how to use javascript to download multiple files, that is, when a user clicks a link or button, download multiple files at the same time. The "simultaneous" here is not very accurate. In modern browsers, multiple files can be downloaded in parallel, while in some old browsers, such as IE8-, such browsers can only download a single file, but we can save multiple files in turn, which is a serial download ~

To ignore the implementation details, you can skip directly to Part 3, or poke:

Code encapsulation: lib. js

DEMO: javascript-multiple-download (HTTPS, the third has bug, the specific reasons are explained below)

javascript-multiple-download (HTTP, normal test)

1. Introduction of document types and their characteristics

1. 1 generic type

Usually, there are various file formats such as txt, png, jpg, zip, tar, etc. Among these file formats, one part of the browser will directly open the link to display the content, while the other part, the browser does not recognize the response header or cannot parse the corresponding format, so it is downloaded directly as a file. Such as:


<a href="http://barretlee.com/test.rar" rel="external nofollow" >file</a>

This code, if you click on the link directly, the browser will download the file directly.

2. dataURL type

dataURL is also a common type of 10 points, which can be sent as a parameter to src or url (). The more common ones are as follows:


 Text:  data:text/plain; Here is the text. 
 Picture:  data:image/jpg;base64,/9j/4AAQSkZJRgABAQEA....
  data:image/png;base64,/9j/4AAQSkZJRgABAQEA....

base64 is a widely used data format.


Base64 Format 
data:[][;charset=][;base64],

Base64  In CSS Use in: 
.demoImg{ background-image: url("data:image/jpg;base64,/9j/4QMZRXhpZgAASUkqAAgAAAAL...."); }

Base64  In HTML Use in: 
<img width="40" height="30" src="data:image/jpg;base64,/9j/4QMZRXhpZgAASUkqAAgAAAAL...." />  

3. Blob Stream

Blob objects represent immutable class file objects that contain raw data. See the MDN documentation for details.

His use is also particularly convenient, such as:


var aFileParts = ['<a id="a"><b id="b">hey!</b></a>'];
var oMyBlob = new Blob(aFileParts, {type : 'text/html'}); // the blob

Blob receives two parameters, one is an array type data object, which can be ArrayBuffer, ArrayBufferView, Blob, String and many other types; The second parameter is the MINE type setting. In this paper, we want to use the function URLcreateObjectURL (), which converts the content represented by an URL into an DOMString, and the result is a file object or an Blob object.

4. Binary flow

When we use File API to read files, we get the binary stream format of data. These types can be directly received by ArrayBuffer, etc., which are not used in this article, so we will not elaborate.

2. JavaScript multi-file download

a tag in HTML5 has one more attribute-download. When the user clicks on the link, the browser will open and display the content of the link. If the download attribute is added to the link, clicking on the link will not open the file, but download it directly. Although it is easy to use, lower browsers are incompatible, and this will be solved in Articles 2 and 3 of this section.

Here, we can use attribute detection UA to determine the browser type:


h5Down = document.createElement("a").hasOwnProperty("download");
var h5Down = !/Trident|MSIE/.test(navigator.userAgent); // Trident  Identification  IE11

1. Use of the download attribute of the a tag

Note: The download property is not supported by FF5.0/Safari5.0/Opera11.1/IE9.0

Using download attribute, you can download a single file directly. If you want to download multiple files at one time, you have to deal with it a little:


function downloadFile(fileName, content){
 var aLink = document.createElement("a"),
  evt = document.createEvent("HTMLEvents");

 evt.initEvent("click");
 aLink.download = fileName;
 aLink.href = content;

 aLink.dispatchEvent(evt);
}

The download attribute does not only make the browser ignore the MIME type of the file, but also takes the value of the attribute as the file name. You can run this program on the chrome console:


downloadFile("barretlee.html", "./");

The browser will prompt whether to keep (download) the html file. We mentioned earlier that the file type may also be dataURL or Blob stream. In order for the program to support these data types, modify the above function slightly:


function downloadFile(fileName, content){
 var aLink = document.createElement('a');
  , blob = new Blob([content])
  , evt = document.createEvent("HTMLEvents");

 evt.initEvent("click");

 aLink.download = fileName;
 aLink.href = URL.createObjectURL(blob);
 aLink.dispatchEvent(evt);
}

new Blob ([content]), now convert the file to an Blog stream, and then convert it to an DOMString using URL. createObjectURL (). In this way, we support data64 and content of other data types ~

2. window. execCommand after open ("SaveAs")

As mentioned above, although the download attribute is a 10-point convenient H5 tool, the lower version of IE is not attractive at all. There are many ways to convert IE. For example, the activeX object of ADOBE. STREAM can convert a file into a file stream and then write it to a file to be saved. What we want to talk about here is a slightly convenient way: first write the content into a newly opened window object, and then use execCommand to execute the save command, which is equivalent to pressing Ctrl+S on the page, so that all the information in the page will be down.


//  Put the file in the 1 A  window  Window, and hide the window. 
var win = window.open("path/to/file.ext", "new Window", "width=0,height=0");
//  In  win  Press in the window  ctrl+s  Save the contents of the window 
win.document.execCommand("SaveAs", true, "filename.ext");
//  When you are used up, close the window 
win.close();

This process is clear, but there will be a problem here, not a program problem, but a browser problem. If we open a new window with Sogou Browser or 360 Browser, he will open a new tab instead of a new window. What's more, some browsers intercept the window of window. open (this can be set). So I had to find another way.

3. Operation in iframe

Since opening a new window is so troublesome, I will finish my work under this window ~


function IEdownloadFile(fileName, contentOrPath){
 var ifr = document.createElement('iframe');

 ifr.style.display = 'none';
 ifr.src = contentOrPath;

 document.body.appendChild(ifr);


 //  Save Page  ->  Save a file 
 ifr.contentWindow.document.execCommand('SaveAs', false, fileName);
 document.body.removeChild(ifr);
}

We can directly add the src attribute to iframe and then execute the saveAs command. What if we are using an data64 encoded file?


 Text:  data:text/plain; Here is the text. 
 Picture:  data:image/jpg;base64,/9j/4AAQSkZJRgABAQEA....
  data:image/png;base64,/9j/4AAQSkZJRgABAQEA....
0

This is also relatively easy to handle, directly write the file to iframe, and then save in the execution.

3. Code encapsulation and interface introduction

1. Encapsulation of code and associated DEMO

Package: lib. js

DEMO: javascript-multiple-download (HTTPS, bug in the third)

javascript-multiple-download (HTTP, normal test)

Bug shows that it is basically compatible with all browsers after one detail processing. I put the code on https://raw.github.com for hosting, probably because it is https transmission, and an error was reported in the third test. The specific content of the error report is: HTTPS security is threatened by http://rawgithub.com/barretlee/javascript-multiple-download/master/file/test.jpg The test results under http protocol are considerable. (I didn't delve into this point. There must be deep security reasons. Is it because he is in jpg picture format? Xie @ Qu Qu reminded that there are security problems in cross-protocol transmission.) I put demo on BAE, and there is no problem, but I didn't test safari and opera.

2. Calling the interface

Three interfaces are provided, which support single file download, multi-file download and multi-file download custom naming.

1) Single file download


 Text:  data:text/plain; Here is the text. 
 Picture:  data:image/jpg;base64,/9j/4AAQSkZJRgABAQEA....
  data:image/png;base64,/9j/4AAQSkZJRgABAQEA....
1

2) Multiple file downloads


 Text:  data:text/plain; Here is the text. 
 Picture:  data:image/jpg;base64,/9j/4AAQSkZJRgABAQEA....
  data:image/png;base64,/9j/4AAQSkZJRgABAQEA....
2

3) Multi-file download custom naming


Downer({
 "1.txt":"./file/test.txt",
 "2.jpg":"./file/test.jpg"
}); 

File URL such as./file/test. jpg can be changed to base64 or other formats, such as:


 Text:  data:text/plain; Here is the text. 
 Picture:  data:image/jpg;base64,/9j/4AAQSkZJRgABAQEA....
  data:image/png;base64,/9j/4AAQSkZJRgABAQEA....
4

Only chrome compatibility is achieved here, and I am too lazy to see it under IE. This demand is rare!

4. Server support and back-end implementation

1. Backend implementation

Instead of using the front end, the principle of direct back-end implementation is to add a special tag to the response header, such as the front end sending such a request:


 Text:  data:text/plain; Here is the text. 
 Picture:  data:image/jpg;base64,/9j/4AAQSkZJRgABAQEA....
  data:image/png;base64,/9j/4AAQSkZJRgABAQEA....
5

The response of the back end is


 Text:  data:text/plain; Here is the text. 
 Picture:  data:image/jpg;base64,/9j/4AAQSkZJRgABAQEA....
  data:image/png;base64,/9j/4AAQSkZJRgABAQEA....
6

Tell the browser this is a stream file, as an attachment to you, please ignore MINE type, save directly.

2. Server configuration

If the background is apche as the server, you can configure the htaccess file:


 Text:  data:text/plain; Here is the text. 
 Picture:  data:image/jpg;base64,/9j/4AAQSkZJRgABAQEA....
  data:image/png;base64,/9j/4AAQSkZJRgABAQEA....
7

This means adding a response header for Content-Disposition: attachment whenever the request is for a file of type zip or rar. In this way, you can omit troublesome operations in php code.

5. Summary

Due to the hasty writing, there will be many mistakes in the text, and there are better proposals for multi-file downloading. I hope to share them together!

There are definitely more ways to download multiple files than mentioned above, and the code I encapsulate here is not implemented in FF safari opera, because they are not compatible with download attributes. For details, please see caniuse. It is suggested that such things should be handed over to the back end in the project, and a few words of code can be done.

6. References

Create and download the file AlloyTeam with JS on the browser side

Starting file download with Javascript Ahzaz's Blog

Blob Stream MDN


Related articles: