Запуск загрузки большого файла из полностью сформированного ответа
Эта проблема
У меня есть конечная точка Node.js, которая правильно запускает загрузку произвольно большого файла при доступе с использованием следующего:
response.setHeader('Content-disposition', 'attachment; filename=' + fileName);
response.set('Content-Type', 'text/csv');
response.status(200);
result.pipe(response);
где result
поток преобразования, и response
Экспресс-объект
Это прекрасно работает при прямом доступе к конечной точке в Chrome, Firefox, Internet Explorer и т. Д. Проблема возникает при попытке достичь конечной точки при включенной аутентификации на основе токенов.
С точки зрения пользователя, когда они нажимают на кнопку, файл загружается.
Как заставить кнопку нажать на эту конечную точку с правильным токеном аутентификации в заголовке запроса и вызвать загрузку файла?
Мозговой штурм некоторых возможных подходов
Когда пользователь нажимает кнопку, он запускает действие, которое обрабатывается программным обеспечением redux-api-middleware, которое делает
GET
запрос к конечной точке (с токеном аутентификации, автоматически включенным в запрос). Это промежуточное ПО сохраняет ответ в переменной, которая выбирается компонентом React. В этом компоненте React, если используемый браузер (например, Chrome и Opera) поддерживает потоки,response.body
будет существовать, так что вы можете сделать что-то вроде следующего.if (response.body) { const csvReader = response.body.getReader(); const textDecoder = new TextDecoder(); const processCsvRow = (csvRow) => { if (csvRow.done) { console.log('Finished downloading file.'); return Promise.resolve(); } // Write to new file for user to download console.log(textDecoder.decode(csvRow.value, {stream: true})); return csvReader.read().then(processCsvRow); }; csvReader.read().then(processCsvRow); }
При таком подходе мне нужно было бы изучить, как обрабатывать данные, если они принимаются браузером без поддержки потока.
Когда пользователь нажимает кнопку, он запускает действие, которое сохраняет конечную точку в хранилище Redux с помощью редуктора, который запускает компонент React для создания тега привязки, который автоматически щелкается.
const link = document.createElement('a'); document.body.appendChild(link); // Firefox requires the link to be in the body link.href = endPoint; link.target = '_blank'; link.click(); document.body.removeChild(link); // Remove the link when done
где
endPoint
является конечной точкой, которая отвечает с файлом.Этот подход работает, когда аутентификация отключена. Когда аутентификация повторно включена, токен аутентификации должен каким-то образом вводиться в заголовок запроса тега привязки.
- Подобно #2, посмотрите на симуляцию щелчка якоря, создав HTTP-запрос со встроенным токеном аутентификации.
- Объединяя элементы из #1 и #2, когда пользователь нажимает на кнопку, запускается действие, которое отправляет
GET
запрос к конечной точке, который возвращает вторую временную незащищенную конечную точку, которая возвращает фактический ответ файла. Передайте эту временную незащищенную конечную точку тегу привязки в #2. - Как-то перенаправить ответ на новую вкладку / окно.
- Передайте маркер аутентификации в качестве параметра URL (это проблема безопасности), затем используйте #2.
- Создайте новую конечную точку, которая генерирует и возвращает новый временный токен одноразового скачивания. Используйте эту новую конечную точку, чтобы получить временный токен для передачи в качестве параметра URL в исходную конечную точку через #2.