Various ways for the front end to download files

There are still many application scenarios for file downloads involved in the front-end, so how many ways are there for front-end file downloads? What are the advantages and disadvantages of each method? Let's introduce them one by one.

1. a label

It is the simplest way to realize file download through the attribute aof the label , and it is also a common way we use. Let’s look at the sample code first:download

<a href="http://www.baidu.com" download="baidu.html">下载</a>

For the above example, we clicked download and found that it jumped to Baidu's homepage, and did not actually download the file.

Because atag download can only download files of the same origin, if it is a cross-domain file, it includes media files such as pictures, audio and video, which are all previews and cannot be downloaded.

The above code is ato realize the file download directly by writing the label, we can also jsrealize it by writing, the code is as follows:

const a = document.createElement('a')
a.href = 'http://www.baidu.com'
a.download = 'baidu.html'
a.click()

The effect is the same as above, all jump to Baidu's homepage without downloading files.

The key point here is the attribute aof the label , which is newly added.downloadHTML5

Content-DispositionIts function is to specify the downloaded file name. If not specified, the downloaded file name will be determined according to the content of the request . If not Content-Disposition, URLthe last part of the request will be used as the file name.

2. window.open

The above acase of using tags can also window.openbe achieved by using the same effect, the code is as follows:

window.open('http://www.baidu.com', '_blank')

Here _blankis the specified opening method, if not specified, it will be opened on the current page, if specified here _blank, it will be opened on a new page.

The attributes of the same atag downloadcan also be used, the code is as follows:

window.open('http://www.baidu.com', '_blank', 'download=baidu.html')

Of course, this method is also flawed. Compared with atags, this method cannot download .html, .htm, .xml, .xhtmland other files, because these files will be htmltreated as files, so they will be opened directly on the current page.

Similarly, cross-domain files cannot be downloaded, after all, yes window.open, no window.download( window.downloadhypothetical).

3. location.href

This method is window.open(url)the same as that, the code is as follows:

location.href = 'http://www.baidu.com'

This method has window.openall the flaws, so it is not recommended to use, here is only for understanding, so I will not explain too much.

4. location.? other attributes

Others here refer to the properties that can jump to the page, such as location.assign, location.replace, location.reloadetc. These properties can realize file download. The code is as follows:

location.assign('http://www.baidu.com')
location.replace('http://www.baidu.com')
location.reload('http://www.baidu.com')

Here location.reloadis a bit special, its function is to reload the current page, but it can also accept a parameter, this parameter is the page to be jumped, so it can also realize file download.

Of course location.href, the disadvantages of these methods are the same, and there are also the characteristics of each attribute. This is only to expand knowledge, not to explain too much.

5. XMLHttpRequest

This method is what we often call ajaxdownloading, including axios, fetchetc. are the same, the code is as follows:

const xhr = new XMLHttpRequest()
xhr.open('GET', 'http://www.baidu.com')
xhr.send()

xhr.onload = function () {
  const blob = new Blob([xhr.response], { type: 'text/html' })
  const a = document.createElement('a')
  a.href = URL.createObjectURL(blob)
  a.download = 'baidu.html'
  a.click()
}

XMLHttpRequestI won’t talk about related knowledge here , but only talk about the part related to file download.

The main logic here is that when our request is successful, we will get the response body response, which responseis the content we want to download, and then we convert it into an blobobject , and then URL.createObjectURLcreate a file through the attribute of the tag download.urladownload

There are two knowledge points here, one is blobthe object and the other is the object URL.createObjectURL.

5.1 blob

Here is blobthe definition of the object, from MDN [2]:

BlobObject represents a file-like object of immutable, primitive data. Its data can be read in text or binary format, and can also be converted  ReadableStream for data manipulation.

BlobRepresents not necessarily JavaScriptdata in its native format. File The interface is based on  Blob, inherited blobfunctionality from and extended to support files on the user's system.

blobObject is html5a newly added object, and its function is to store binary data, such as pictures, videos, audio, etc. Its usage is as follows:

/**
 * @param {Array} array 二进制数据
 * @param {Object} options 配置项
 * @param {String} options.type 文件类型,它代表了将会被放入到 blob 中的数组内容的 MIME 类型。
 * @param {String} options.endings 用于指定包含行结束符\n的字符串如何被写入。默认为transparent,表示不会修改行结束符。还可以指定为native,表示会将\n转换为\r\n。
 */
const blob = new Blob([], { type: '' })

The main concern here is typethe attribute. By default, blobthe object has no typeattribute, so this Blobis a typeless Blobfile. The file will not be damaged, but it cannot be recognized normally.

5.2 URL.createObjectURL

The following is from MDN [3]:

The URL.createObjectURL() static method creates a DOMString containing a URL representing the object given in the parameter. The lifetime of this URL is bound to the document in the window that created it. This new URL object represents the specified File object or Blob object.

This method is used to create one url. Its function is to blobconvert an object into one url. This method urlcan be used to download files or preview files. The code is as follows:

const url = URL.createObjectURL(blob)

What needs to be noted here is that urlthe life cycle of this is bound to the window that created it document, that is to say, when ours documentis destroyed, this urlwill become invalid, so we need to destroy it at the right time. The code is as follows:

URL.revokeObjectURL(url)

Going back to the problem we just downloaded, we blobsolve it through objects, but our typeattributes are hard-coded. If the file type is determined, there is no problem, but if this interface is the interface for downloading files, the file may There are various types, how should we deal with them?

There is no correct answer here. The first one can be negotiated with the interface provider. The negotiation plan is uncertain. The second is to obtain the file through responseit , which is what we want to talk about:headertype

const type = response.headers['content-type']

const blob = new Blob([response.data], { type })

Here we get it responsethrough , and then create the object, so that the file can be downloaded correctly.headertypeblob

In fact , content-typeit may be that application/octet-streamat this time we need to file-typeget the file through type.

The following code is passed file-typeto get the file type:

import {fileTypeFromStream} from 'file-type';

const type = await fileTypeFromStream(response.body);
const blob = new Blob([response.data], { type })

6. Summary

There are so many solutions above, in fact, it still falls on athe label in the end, so whether it is downloaded through the built-in behavior of the browser or through ajaxthe download, the final file download is the behavior of the browser.

---END---

Guess you like

Origin blog.csdn.net/qq_44848480/article/details/129236595