Термин «контекст» иногда используется для ссылки на объект, на который это ссылается. Его использование неуместно, потому что оно не подходит семантически или технически с помощью ECMAScript.
ECMAScript это означает обстоятельства, окружающие что-то, что добавляет смысл, или некоторые предыдущие и последующие данные, которые дает дополнительный смысл. Термин «контекст» используется в ECMAScript для ссылки на this , который представляет собой все параметры, область действия и этот в рамках некоторого исполняемого кода.
В показано это :
Задайте значение ThisBinding тем же значением, что и ThisBinding для контекста выполнения вызова], который четко указывает, что это часть контекста выполнения.
Контекст выполнения предоставляет информацию, которая добавляет смысл исполняемому коду. Он содержит гораздо больше информации, что только thisBinding.
Таким образом, значение этого не является «контекстом», это всего лишь одна часть контекста выполнения. Это, по сути, локальная переменная, которая может быть задана вызовом любого объекта и в строгом режиме для любого значения вообще.
Поддержка загрузки двоичных файлов при использовании ajax невелика, она все еще находится в разработке как рабочие черновики .
Вы можете загрузить браузер для загрузки запрошенного файла, просто используя приведенный ниже код, и это поддерживается во всех браузерах и, очевидно, вызовет запрос WebApi тот же.
$scope.downloadFile = function(downloadPath) {
window.open(downloadPath, '_blank', '');
}
Использование ajax для загрузки двоичного файла может быть выполнено в некоторых браузерах, а ниже - реализация, которая будет работать в самых последних вариантах Chrome, Internet Explorer, FireFox и Safari.
Он использует тип ответа arraybuffer
, который затем преобразуется в JavaScript blob
, который затем либо предоставляется для сохранения с использованием метода saveBlob
- хотя это только сейчас присутствует в Internet Explorer или превращается в URL-адрес данных blob, который открывается браузером, запуская диалог загрузки, если тип mime поддерживается для просмотра в браузере.
Примечание. Internet Explorer 11 не любил использовать функцию msSaveBlob
, если она была псевдонимом - возможно, secu но, скорее, недостаток, поэтому использование var saveBlob = navigator.msSaveBlob || navigator.webkitSaveBlob ... etc.
для определения доступной поддержки saveBlob
вызвало исключение; поэтому теперь код ниже проверяется отдельно для navigator.msSaveBlob
. Благодаря? Microsoft
// Based on an implementation here: web.student.tuwien.ac.at/~e0427417/jsdownload.html
$scope.downloadFile = function(httpPath) {
// Use an arraybuffer
$http.get(httpPath, { responseType: 'arraybuffer' })
.success( function(data, status, headers) {
var octetStreamMime = 'application/octet-stream';
var success = false;
// Get the headers
headers = headers();
// Get the filename from the x-filename header or default to "download.bin"
var filename = headers['x-filename'] || 'download.bin';
// Determine the content type from the header or default to "application/octet-stream"
var contentType = headers['content-type'] || octetStreamMime;
try
{
// Try using msSaveBlob if supported
console.log("Trying saveBlob method ...");
var blob = new Blob([data], { type: contentType });
if(navigator.msSaveBlob)
navigator.msSaveBlob(blob, filename);
else {
// Try using other saveBlob implementations, if available
var saveBlob = navigator.webkitSaveBlob || navigator.mozSaveBlob || navigator.saveBlob;
if(saveBlob === undefined) throw "Not supported";
saveBlob(blob, filename);
}
console.log("saveBlob succeeded");
success = true;
} catch(ex)
{
console.log("saveBlob method failed with the following exception:");
console.log(ex);
}
if(!success)
{
// Get the blob url creator
var urlCreator = window.URL || window.webkitURL || window.mozURL || window.msURL;
if(urlCreator)
{
// Try to use a download link
var link = document.createElement('a');
if('download' in link)
{
// Try to simulate a click
try
{
// Prepare a blob URL
console.log("Trying download link method with simulated click ...");
var blob = new Blob([data], { type: contentType });
var url = urlCreator.createObjectURL(blob);
link.setAttribute('href', url);
// Set the download attribute (Supported in Chrome 14+ / Firefox 20+)
link.setAttribute("download", filename);
// Simulate clicking the download link
var event = document.createEvent('MouseEvents');
event.initMouseEvent('click', true, true, window, 1, 0, 0, 0, 0, false, false, false, false, 0, null);
link.dispatchEvent(event);
console.log("Download link method with simulated click succeeded");
success = true;
} catch(ex) {
console.log("Download link method with simulated click failed with the following exception:");
console.log(ex);
}
}
if(!success)
{
// Fallback to window.location method
try
{
// Prepare a blob URL
// Use application/octet-stream when using window.location to force download
console.log("Trying download link method with window.location ...");
var blob = new Blob([data], { type: octetStreamMime });
var url = urlCreator.createObjectURL(blob);
window.location = url;
console.log("Download link method with window.location succeeded");
success = true;
} catch(ex) {
console.log("Download link method with window.location failed with the following exception:");
console.log(ex);
}
}
}
}
if(!success)
{
// Fallback to window.open method
console.log("No methods worked for saving the arraybuffer, using last resort window.open");
window.open(httpPath, '_blank', '');
}
})
.error(function(data, status) {
console.log("Request failed with status: " + status);
// Optionally write the error out to scope
$scope.errorDetails = "Request failed with status: " + status;
});
};
var downloadPath = "/files/instructions.pdf";
$scope.downloadFile(downloadPath);
Вы должны изменить свой метод WebApi, чтобы вернуть следующие заголовки:
x-filename
для отправки имени файла. Это удобный пользовательский заголовок для удобства, однако вы можете извлечь имя файла из заголовка content-disposition
с помощью регулярных выражений. content-type
для вашего ответа, так что браузер знает формат данных. Надеюсь, это поможет.
Нам также пришлось разработать решение, которое даже работало бы с API-интерфейсами, требующими аутентификации (см. в этой статье )
. Использование AngularJS в двух словах здесь заключается в том, как мы это сделали:
Шаг 1: Создайте специальную директиву
// jQuery needed, uses Bootstrap classes, adjust the path of templateUrl
app.directive('pdfDownload', function() {
return {
restrict: 'E',
templateUrl: '/path/to/pdfDownload.tpl.html',
scope: true,
link: function(scope, element, attr) {
var anchor = element.children()[0];
// When the download starts, disable the link
scope.$on('download-start', function() {
$(anchor).attr('disabled', 'disabled');
});
// When the download finishes, attach the data to the link. Enable the link and change its appearance.
scope.$on('downloaded', function(event, data) {
$(anchor).attr({
href: 'data:application/pdf;base64,' + data,
download: attr.filename
})
.removeAttr('disabled')
.text('Save')
.removeClass('btn-primary')
.addClass('btn-success');
// Also overwrite the download pdf function to do nothing.
scope.downloadPdf = function() {
};
});
},
controller: ['$scope', '$attrs', '$http', function($scope, $attrs, $http) {
$scope.downloadPdf = function() {
$scope.$emit('download-start');
$http.get($attrs.url).then(function(response) {
$scope.$emit('downloaded', response.data);
});
};
}]
});
Шаг 2. Создайте шаблон
<a href="" class="btn btn-primary" ng-click="downloadPdf()">Download</a>
Шаг 3: Используйте его
<pdf-download url="/some/path/to/a.pdf" filename="my-awesome-pdf"></pdf-download>
Это приведет к синей кнопке. При нажатии на него будет загружен PDF-файл (Внимание: бэкэнд должен доставить PDF-код в кодировке Base64!) И ввести в href. Кнопка станет зеленой и переключит текст на Сохранить . Пользователь может снова щелкнуть и будет представлен стандартный диалог файла загрузки для файла my-awesome.pdf .
Для меня веб-API был Rails и клиентской стороной Angular, используемой с Restangular и FileSaver.js
веб-API
module Api
module V1
class DownloadsController < BaseController
def show
@download = Download.find(params[:id])
send_data @download.blob_data
end
end
end
end
HTML
<a ng-click="download('foo')">download presentation</a>
Угловой контроллер
$scope.download = function(type) {
return Download.get(type);
};
Угловая служба
'use strict';
app.service('Download', function Download(Restangular) {
this.get = function(id) {
return Restangular.one('api/v1/downloads', id).withHttpConfig({responseType: 'arraybuffer'}).get().then(function(data){
console.log(data)
var blob = new Blob([data], {
type: "application/pdf"
});
//saveAs provided by FileSaver.js
saveAs(blob, id + '.pdf');
})
}
});
В вашем компоненте i.e угловой код js:
function getthefile (){
window.location.href='http://localhost:1036/CourseRegConfirm/getfile';
};
Вы можете реализовать функцию showfile, которая принимает параметры данных, возвращаемых из WEBApi, и имя файла для файла, который вы пытаетесь загрузить. То, что я сделал, это создать отдельный браузер, который определяет браузер пользователя, а затем обрабатывает рендеринг файла на основе браузера. Например, если целевым браузером является хром на ipad, вы должны использовать javascripts объект FileReader.
FileService.showFile = function (data, fileName) {
var blob = new Blob([data], { type: 'application/pdf' });
if (BrowserService.isIE()) {
window.navigator.msSaveOrOpenBlob(blob, fileName);
}
else if (BrowserService.isChromeIos()) {
loadFileBlobFileReader(window, blob, fileName);
}
else if (BrowserService.isIOS() || BrowserService.isAndroid()) {
var url = URL.createObjectURL(blob);
window.location.href = url;
window.document.title = fileName;
} else {
var url = URL.createObjectURL(blob);
loadReportBrowser(url, window,fileName);
}
}
function loadFileBrowser(url, window, fileName) {
var iframe = window.document.createElement('iframe');
iframe.src = url
iframe.width = '100%';
iframe.height = '100%';
iframe.style.border = 'none';
window.document.title = fileName;
window.document.body.appendChild(iframe)
window.document.body.style.margin = 0;
}
function loadFileBlobFileReader(window, blob,fileName) {
var reader = new FileReader();
reader.onload = function (e) {
var bdata = btoa(reader.result);
var datauri = 'data:application/pdf;base64,' + bdata;
window.location.href = datauri;
window.document.title = fileName;
}
reader.readAsBinaryString(blob);
}
BrowserService
. Кроме того, ваши функции, с которыми вы ссылаетесь, имеют неправильное имя. loadReportBlobFileReader
вместо loadFileBlobFileReader
. url
, который вы не используете, если это IE, Chrome или iOS или Android. Установив window
на возврат msSaveOrOpenBlob
..., он возвращает boolean
. Установка window.document.title
после изменения location.href
] В чем смысл? Нужен рефакторинг.
– Scott
26 May 2016 в 12:01
Отправьте файл как строку base64.
var element = angular.element('<a/>');
element.attr({
href: 'data:attachment/csv;charset=utf-8,' + encodeURI(atob(response.payload)),
target: '_blank',
download: fname
})[0].click();
Если метод attr не работает в Firefox, вы также можете использовать метод javaScript setAttribute
C # WebApi PDF скачать все, работающие с Angular JS Authentication
Web Api Controller
[HttpGet]
[Authorize]
[Route("OpenFile/{QRFileId}")]
public HttpResponseMessage OpenFile(int QRFileId)
{
QRFileRepository _repo = new QRFileRepository();
var QRFile = _repo.GetQRFileById(QRFileId);
if (QRFile == null)
return new HttpResponseMessage(HttpStatusCode.BadRequest);
string path = ConfigurationManager.AppSettings["QRFolder"] + + QRFile.QRId + @"\" + QRFile.FileName;
if (!File.Exists(path))
return new HttpResponseMessage(HttpStatusCode.BadRequest);
HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
//response.Content = new StreamContent(new FileStream(localFilePath, FileMode.Open, FileAccess.Read));
Byte[] bytes = File.ReadAllBytes(path);
//String file = Convert.ToBase64String(bytes);
response.Content = new ByteArrayContent(bytes);
response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
response.Content.Headers.ContentDisposition.FileName = QRFile.FileName;
return response;
}
Угловая служба JS
this.getPDF = function (apiUrl) {
var headers = {};
headers.Authorization = 'Bearer ' + sessionStorage.tokenKey;
var deferred = $q.defer();
$http.get(
hostApiUrl + apiUrl,
{
responseType: 'arraybuffer',
headers: headers
})
.success(function (result, status, headers) {
deferred.resolve(result);;
})
.error(function (data, status) {
console.log("Request failed with status: " + status);
});
return deferred.promise;
}
this.getPDF2 = function (apiUrl) {
var promise = $http({
method: 'GET',
url: hostApiUrl + apiUrl,
headers: { 'Authorization': 'Bearer ' + sessionStorage.tokenKey },
responseType: 'arraybuffer'
});
promise.success(function (data) {
return data;
}).error(function (data, status) {
console.log("Request failed with status: " + status);
});
return promise;
}
Угловой JS-контроллер, вызывающий службу
vm.open3 = function () {
var downloadedData = crudService.getPDF('ClientQRDetails/openfile/29');
downloadedData.then(function (result) {
var file = new Blob([result], { type: 'application/pdf;base64' });
var fileURL = window.URL.createObjectURL(file);
var seconds = new Date().getTime() / 1000;
var fileName = "cert" + parseInt(seconds) + ".pdf";
var a = document.createElement("a");
document.body.appendChild(a);
a.style = "display: none";
a.href = fileURL;
a.download = fileName;
a.click();
});
};
И последняя страница HTML
<a class="btn btn-primary" ng-click="vm.open3()">FILE Http with crud service (3 getPDF)</a>
Это будет рефакторинг, просто обменяв код, теперь надеемся, что это поможет кто-то, так как мне потребовалось некоторое время, чтобы заставить это работать.
window.open
. – Scott 26 May 2016 в 01:55