1. метка, 2. window.open, 3. location.href, 4. location.? Другие свойства и 5. XMLHttpRequest. Каковы плюсы и минусы каждого метода?

Загрузка файла во внешнем интерфейсе по-прежнему имеет множество сценариев применения, так сколько же существует способов загрузки файла во внешнем интерфейсе? Каковы преимущества и недостатки каждого метода? Давайте представим их один за другим.

1. этикетка

Загрузка файла осуществляется с помощью атрибута загрузки тега a. Этот метод является самым простым и наиболее часто используемым методом. Давайте сначала посмотрим на пример кода:

<a href="http://www.google.com" download="google.html">download</a>

В приведенном выше примере мы нажали «Загрузить» и обнаружили, что перешли на главную страницу Google и фактически не загружали файл.
Поскольку загрузка тега может загружать только файлы одного и того же происхождения, если это кросс- файл домена, включая изображения, аудио- и видеофайлы, а также другие мультимедийные файлы, это предварительный просмотр, который нельзя загрузить.
Вышеприведенный код предназначен для прямой загрузки файла путем написания тега, мы также можем добиться этого с помощью js, код выглядит следующим образом:

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

Эффект такой же, как и выше, он переходит на главную страницу Baidu без загрузки файлов.
Здесь основное внимание уделяется атрибуту загрузки тега, который является новым в HTML5.
Его функция заключается в указании загруженного имя файла. Если он не указан, имя загружаемого файла будет определяться в соответствии с Content-Disposition запрошенного контента. Если Content-Disposition отсутствует, то в качестве имени файла будет использоваться последняя часть запрошенного URL.

2. окно.открыть

Вышеприведенный случай использования тега также может быть достигнут через window.open, эффект тот же, и код выглядит следующим образом:

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

Здесь _blank — это способ указать открытие. Если не указано, он будет открыт на текущей странице. Указание здесь _blank означает открытие на новой странице.

Также можно использовать атрибут загрузки тега, код выглядит следующим образом:

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

Конечно, этот метод тоже несовершенен. По сравнению с тегом, этот метод не может загружать файлы .html, .htm, .xml, .xhtml и другие, поскольку эти файлы будут обрабатываться как файлы HTML, поэтому они будут непосредственно на текущей странице. Открыть.
Также невозможно загружать междоменные файлы. Ведь это window.open, а не window.download (window.download — воображаемый).

3. location.href

Этот метод такой же, как и window.open(url), код выглядит следующим образом:

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

Этот метод имеет все недостатки window.open, поэтому использовать его не рекомендуется. Здесь он используется только для понимания, поэтому я не буду слишком много объяснять.

4. расположение.? Другие свойства

Другие здесь относятся к свойствам, которые могут переходить на страницу, например, location.assign, location.replace, location.reload и т. д. Эти свойства могут осуществлять загрузку файла, код выглядит следующим образом:

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

Здесь location.reload немного особенный, его функция заключается в перезагрузке текущей страницы, но он также может принимать параметр, этот параметр является страницей, на которую нужно перейти, поэтому он также может выполнять загрузку файла.
Конечно. , как и location.href, эти методы имеют те же недостатки, а также имеют свои особенности каждого атрибута. Это только для расширения знаний, а не для объяснения лишнего.

5. XMLHttpRequest

Этот метод мы часто называем загрузкой ajax, в том числе Axios, fetch и т. д. одинаковы, код выглядит следующим образом:

const xhr = new XMLHttpRequest()
xhr.open('GET', 'http://www.google.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 = 'google.html'
  a.click()
}

Я не буду здесь рассказывать о знаниях, связанных с XMLHttpRequest, а только о той части, которая связана с загрузкой файла.
Основная логика здесь заключается в том, что когда наш запрос будет успешным, мы получим ответ тела ответа, этот ответ содержимое, которое мы хотим загрузить, а затем преобразуем его в объект BLOB-объекта, а затем создаем URL-адрес с помощью URL.createObjectURL, а затем загрузка файла осуществляется с помощью атрибута загрузки тега a.
Есть два знания. указывает здесь, один — это объект большого двоичного объекта, а другой — URL.createObjectURL.

5.1 капля

Вот определение объекта blob из MDN:

The Blob object represents a blob, which is a file-like object of immutable, raw data; they can be read as text or binary data, or converted into a ReadableStream so its methods can be used for processing the data.
Blobs can represent data that isn't necessarily in a JavaScript-native format. The File interface is based on Blob, inheriting blob functionality and expanding it to support files on the user's system.

Объект blob — это новый объект в html5. Его функция заключается в хранении двоичных данных, таких как изображения, видео, аудио и т. д. Его использование заключается в следующем:

/**
 * @param {Array}  array binary data
 * @param {Object} options configuration item
 *      @param {String} options.type The file type, which represents the MIME type of the array contents that will be put into the blob.
 *      @param {String} options.endings Used to specify how strings containing line terminators \n are written. Defaults to transparent, which means that line terminators will not be modified. It can also be specified as native, which means that \n will be converted to \r\n.
 */
const blob = new Blob([], { type: '' })

Основной проблемой здесь является атрибут типа. По умолчанию объект blob не имеет атрибута type, поэтому blob является нетипизированным blob, и файл не будет поврежден, но его нельзя будет нормально распознать.

5.2 URL.createObjectURL

Вот от MDN:

The URL.createObjectURL() static method creates a string containing a URL representing the object given in the parameter.
The URL lifetime is tied to the document in the window on which it was created. The new object URL represents the specified File object or Blob object.

Этот метод используется для создания URL-адреса. Его функция заключается в преобразовании объекта BLOB-объекта в URL-адрес. Этот URL-адрес можно использовать для загрузки файлов или предварительного просмотра файлов. Код выглядит следующим образом:

const url = URL.createObjectURL(blob)

Здесь следует отметить, что жизненный цикл этого URL-адреса привязан к документу в окне, которое его создало, то есть, когда наш документ будет уничтожен, URL-адрес будет недействительным, поэтому нам нужно уничтожить его справа время, код показывает, как показано ниже:

URL.revokeObjectURL(url)

Вернемся к проблеме, которую мы только что загрузили, мы решили ее с помощью объекта blob, но наш атрибут type жестко запрограммирован. Если тип файла определяется, то проблем нет, но если этот интерфейс интерфейс для скачивания файлов, Файлы могут быть разных типов, что с ними делать?
Здесь нет правильного ответа. Первый — договориться с поставщиком интерфейса. Схема переговоров не определена. Второй — получить тип файла через заголовок ответа, о чем мы и хотим поговорить:

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

Здесь мы получаем тип через заголовок ответа, а затем создаем объект blob, чтобы файл можно было загрузить корректно.
На самом деле, content-type также может быть application/octet-stream. В настоящее время нам нужно получить тип файла через тип файла.
Следующий код использует тип файла для получения типа файла:

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

Использование типа файла может быть упомянуто здесь.

Подведем итог

Решений очень много выше, но по факту в итоге падает на тег, так что скачивается ли через встроенное поведение браузера или скачивается через ajax, окончательная загрузка файла это поведение браузера.

Дополнительные материалы на PlainEnglish.io. Подпишитесь на нашу бесплатную еженедельную рассылку новостей. Подпишитесь на нас в Twitter, LinkedIn, YouTube и Discord . Заинтересованы в хакинге роста? Ознакомьтесь с разделом Схема.