Как настроить заголовок для HTTP-запроса GET и загрузить файл запуска?
Обновить 20140702:
(но я отмечаю один из других ответов как принятый вместо моего собственного,
как он получил меня на полпути и вознаградить усилия)
Похоже, что настройка заголовка HTTP-запроса невозможна через ссылки с <a href="...">
и может выполняться только с помощью XMLHttpRequest
.
Однако URL-адрес, связанный с файлом, должен быть загружен (браузер не должен перейти к его URL-адресу), и я не уверен, что это можно сделать с помощью AJAX.
Кроме того, возвращаемый файл является двоичным файлом, и AJAX не предназначен для этого.
Как можно запускать загрузку файла с помощью HTTP-запроса с добавленным пользовательским заголовком?
изменить: исправить неработающую ссылку
Ответы
Ответ 1
Try
HTML
<!-- placeholder ,
`click` download , `.remove()` options ,
at js callback , following js
-->
<a>download</a>
JS
$(document).ready(function () {
$.ajax({
// `url`
url: '/echo/json/',
type: "POST",
dataType: 'json',
// `file`, data-uri, base64
data: {
json: JSON.stringify({
"file": "data:text/plain;base64,YWJj"
})
},
// `custom header`
headers: {
"x-custom-header": 123
},
beforeSend: function (jqxhr) {
console.log(this.headers);
alert("custom headers" + JSON.stringify(this.headers));
},
success: function (data) {
// `file download`
$("a")
.attr({
"href": data.file,
"download": "file.txt"
})
.html($("a").attr("download"))
.get(0).click();
console.log(JSON.parse(JSON.stringify(data)));
},
error: function (jqxhr, textStatus, errorThrown) {
console.log(textStatus, errorThrown)
}
});
});
jsfiddle http://jsfiddle.net/guest271314/SJYy3/
Ответ 2
Существует два способа: загрузить файл, где для HTTP-запроса требуется установить заголовок.
Кредит для первого отправляется на @guest271314, а кредит для второго - @dandavis.
Первый способ - использовать API файлов HTML5 для создания временного локального файла,
а второй - использовать кодировку base64 в сочетании с URI данных.
В моем проекте, используемом в моем проекте, используется метод кодирования base64 для небольших файлов,
или когда API файлов недоступен,
в противном случае используется подход File API.
Решение:
var id = 123;
var req = ic.ajax.raw({
type: 'GET',
url: '/api/dowloads/'+id,
beforeSend: function (request) {
request.setRequestHeader('token', 'token for '+id);
},
processData: false
});
var maxSizeForBase64 = 1048576; //1024 * 1024
req.then(
function resolve(result) {
var str = result.response;
var anchor = $('.vcard-hyperlink');
var windowUrl = window.URL || window.webkitURL;
if (str.length > maxSizeForBase64 && typeof windowUrl.createObjectURL === 'function') {
var blob = new Blob([result.response], { type: 'text/bin' });
var url = windowUrl.createObjectURL(blob);
anchor.prop('href', url);
anchor.prop('download', id+'.bin');
anchor.get(0).click();
windowUrl.revokeObjectURL(url);
}
else {
//use base64 encoding when less than set limit or file API is not available
anchor.attr({
href: 'data:text/plain;base64,'+FormatUtils.utf8toBase64(result.response),
download: id+'.bin',
});
anchor.get(0).click();
}
}.bind(this),
function reject(err) {
console.log(err);
}
);
Обратите внимание, что я не использую raw XMLHttpRequest
,
и вместо этого используя ic-ajax,
и должно быть очень похоже на решение jQuery.ajax
.
Заметим также, что вы должны подставить text/bin
и .bin
все, что соответствует загружаемому типу файла.
Реализация FormatUtils.utf8toBase64
можно найти здесь
Ответ 3
Я добавляю еще один вариант. Ответы выше были очень полезны для меня, но я хотел использовать jQuery вместо ic-ajax (он, похоже, имеет зависимость от Ember, когда я пытался установить через bower). Имейте в виду, что это решение работает только в современных браузерах.
Чтобы реализовать это на jQuery, я использовал jQuery BinaryTransport. Это хороший плагин для чтения ответов AJAX в двоичном формате.
Затем вы можете сделать это, чтобы загрузить файл и отправить заголовки:
$.ajax({
url: url,
type: 'GET',
dataType: 'binary',
headers: headers,
processData: false,
success: function(blob) {
var windowUrl = window.URL || window.webkitURL;
var url = windowUrl.createObjectURL(blob);
anchor.prop('href', url);
anchor.prop('download', fileName);
anchor.get(0).click();
windowUrl.revokeObjectURL(url);
}
});
Классы в приведенном выше script означают:
- url: URL-адрес файла
Заголовки
- : объект Javascript с заголовками для отправки
- имя_файла: имя файла, которое пользователь увидит при загрузке файла
- anchor: это элемент DOM, который необходим для имитации загрузки, которая в этом случае должна быть обернута jQuery. Например
$('a.download-link')
.
Ответ 4
Я хочу опубликовать мое решение здесь, которое было сделано AngularJS, ASP.NET MVC. Код иллюстрирует, как загрузить файл с аутентификацией.
Метод WebApi вместе со вспомогательным классом:
[RoutePrefix("filess")]
class FileController: ApiController
{
[HttpGet]
[Route("download-file")]
[Authorize(Roles = "admin")]
public HttpResponseMessage DownloadDocument([FromUri] int fileId)
{
var file = "someFile.docx"// asking storage service to get file path with id
return Request.ReturnFile(file);
}
}
static class DownloadFIleFromServerHelper
{
public static HttpResponseMessage ReturnFile(this HttpRequestMessage request, string file)
{
var result = request.CreateResponse(HttpStatusCode.OK);
result.Content = new StreamContent(new FileStream(file, FileMode.Open, FileAccess.Read));
result.Content.Headers.Add("x-filename", Path.GetFileName(file)); // letters of header names will be lowercased anyway in JS.
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileName = Path.GetFileName(file)
};
return result;
}
}
Изменения в файле Web.config позволяют отправлять имя файла в пользовательский заголовок.
<configuration>
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Methods" value="POST,GET,PUT,PATCH,DELETE,OPTIONS" />
<add name="Access-Control-Allow-Headers" value="Authorization,Content-Type,x-filename" />
<add name="Access-Control-Expose-Headers" value="Authorization,Content-Type,x-filename" />
<add name="Access-Control-Allow-Origin" value="*" />
Angular Часть обслуживания JS:
function proposalService($http, $cookies, config, FileSaver) {
return {
downloadDocument: downloadDocument
};
function downloadFile(documentId, errorCallback) {
$http({
url: config.apiUrl + "files/download-file?documentId=" + documentId,
method: "GET",
headers: {
"Content-type": "application/json; charset=utf-8",
"Authorization": "Bearer " + $cookies.get("api_key")
},
responseType: "arraybuffer"
})
.success( function(data, status, headers) {
var filename = headers()['x-filename'];
var blob = new Blob([data], { type: "application/octet-binary" });
FileSaver.saveAs(blob, filename);
})
.error(function(data, status) {
console.log("Request failed with status: " + status);
errorCallback(data, status);
});
};
};
Зависимость модуля от FileUpload: angular -file-download (gulp install angular -file-download --save). Регистрация выглядит следующим образом.
var app = angular.module('cool',
[
...
require('angular-file-saver'),
])
. // other staff.
Ответ 5
Чистый JQuery.
$.ajax({
type: "GET",
url: "https://example.com/file",
headers: {
'Authorization': 'Bearer eyJraWQiFUDA.......TZxX1MGDGyg'
},
xhrFields: {
responseType: 'blob'
},
success: function (blob) {
var windowUrl = window.URL || window.webkitURL;
var url = windowUrl.createObjectURL(blob);
var anchor = document.createElement('a');
anchor.href = url;
anchor.download = 'filename.zip';
anchor.click();
anchor.parentNode.removeChild(anchor);
windowUrl.revokeObjectURL(url);
},
error: function (error) {
console.log(error);
}
});
Ответ 6
Примечание. Этот ответ не учитывает настройку настраиваемого заголовка из-за неправильного чтения; однако здесь приведены несколько способов запуска загрузки файлов. Благодаря @bguiz и @Vivek для обратной связи.
1) в jQuery
$('a.some-random-link').click(function(e) {
e.preventDefault(); //stop the browser from following
window.location.href = 'uploads/crazy-fractals.jpg';
});
2) в html с атрибутом download
, мой любимый:
<a href="/path/to/file.extension" download>download</a>
ПРОВЕРИТЬ CANIUSE.COM ДЛЯ СОВМЕСТИМОСТИ
3) js, я также иногда видел:
function downloadFileFromLocation(fileName, url) {
var dl = document.createElement('a');
dl.download = fileName;
dl.href = url;
dl.click();
}