ASP에서 파일을 다운로드합니다.Angular를 사용하는 NET Web API 메서드JS
Angular JS 프로젝트에서는<a>
앵커 태그: 클릭하면 HTTP가 생성됩니다.GET
파일을 반환하는 WebAPI 메서드에 대한 요청입니다.
이제 요청이 성공하면 파일을 사용자에게 다운로드해 주었으면 합니다.그걸 어떻게 하는 거죠?
앵커 태그:
<a href="#" ng-click="getthefile()">Download img</a>
AngularJS:
$scope.getthefile = function () {
$http({
method: 'GET',
cache: false,
url: $scope.appPath + 'CourseRegConfirm/getfile',
headers: {
'Content-Type': 'application/json; charset=utf-8'
}
}).success(function (data, status) {
console.log(data); // Displays text data if the file is a text file, binary if it's an image
// What should I write here to download the file I receive from the WebAPI method?
}).error(function (data, status) {
// ...
});
}
My WebAPI 메서드:
[Authorize]
[Route("getfile")]
public HttpResponseMessage GetTestFile()
{
HttpResponseMessage result = null;
var localFilePath = HttpContext.Current.Server.MapPath("~/timetable.jpg");
if (!File.Exists(localFilePath))
{
result = Request.CreateResponse(HttpStatusCode.Gone);
}
else
{
// Serve the file to the client
result = Request.CreateResponse(HttpStatusCode.OK);
result.Content = new StreamContent(new FileStream(localFilePath, FileMode.Open, FileAccess.Read));
result.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
result.Content.Headers.ContentDisposition.FileName = "SampleImg";
}
return result;
}
Ajax를 사용하여 바이너리 파일을 다운로드할 수 있는 지원은 훌륭하지 않습니다.작업 초안으로서 아직 개발 중입니다.
#심플한 다운로드 방법:
아래 코드를 사용하여 브라우저에 요청된 파일을 다운로드하도록 할 수 있습니다.이것은 모든 브라우저에서 지원되며 WebApi 요청도 동일하게 트리거됩니다.
$scope.downloadFile = function(downloadPath) {
window.open(downloadPath, '_blank', '');
}
#Ajax 바이너리 다운로드 방법:
바이너리 파일을 다운로드하기 위해 ajax를 사용하는 것은 일부 브라우저에서 수행할 수 있으며, 아래는 Chrome, Internet Explorer, FireFox 및 Safari의 최신 맛에서 작동하는 구현입니다.
이 제품은arraybuffer
응답 유형(JavaScript로 변환됨)blob
그 후 를 사용하여 저장하도록 표시됩니다.saveBlob
메서드 - 현재 Internet Explorer에만 존재하거나 브라우저에 의해 열리는 블럽 데이터 URL로 변환되어 브라우저에서 볼 수 있는 MIME 유형이 지원되는 경우 다운로드 대화상자를 트리거합니다.
##Internet Explorer 11 지원 (고정) 주의:Internet Explorer 11은 보안 기능을 사용할 수 있지만, 보안 기능을 사용하여 보안 기능을 사용할 수 있지만, VBlobile = 네비게이터를 사용하여 사용할 수 있습니다.웹 키트 저장...사용 가능한 저장소는 예외로 인해 예외로 인해 예외로 인한 코드를 분리하기 위해 아래 코드를 별도로 테스트합니다.ms 저장을 위한 코드를 분리한다. 고마워요? 마이크로소프트
// 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
header를 지정하여 파일 이름을 전송합니다.이것은 편의를 위해 커스텀헤더입니다만, 파일명을 추출할 수 있습니다.content-disposition
header를 지정합니다.를 설정할 필요가 있습니다.
content-type
브라우저가 데이터 형식을 인식할 수 있도록 사용자의 응답에 대한 mime 헤더도 지정합니다.
이게 도움이 됐으면 좋겠어요.
C# WebApi PDF 다운로드 모두 Angular JS 인증으로 동작
웹 API 컨트롤러
[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>
코드 공유만으로 리팩터링 할 수 있습니다.다른 사람에게 도움이 되길 바랍니다.이 작업을 완료하는 데 시간이 좀 걸렸어요.
웹 API는 Rails와 클라이언트 측 Angular로 Resangular 및 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');
})
}
});
또한 인증을 필요로 하는 API에서도 사용할 수 있는 솔루션을 개발해야 했습니다(이 기사 참조).
각도 사용JS는 간단히 다음과 같이 작업을 수행했습니다.
순서 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 파일의 표준 다운로드 파일 대화상자가 나타납니다.
파일을 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();
Firefox에서 attr 메서드가 작동하지 않는 경우 JavaScript setAttribute 메서드를 사용할 수도 있습니다.
WEBApi에서 반환된 데이터의 파라미터와 다운로드하려는 파일의 파일 이름을 가져오는 showfile 함수를 구현할 수 있습니다.저는 별도의 브라우저 서비스를 만들고 사용자의 브라우저를 식별한 후 브라우저에 따라 파일 렌더링을 처리했습니다.예를 들어 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);
}
저는 다양한 솔루션을 검토했습니다.이것이 저에게 있어서 큰 도움이 되었다고 생각합니다.
제 경우, 몇 가지 자격 증명과 함께 포스트 리퀘스트를 보내야 했습니다.스크립트 내부에 jquery를 추가하는 것이 작은 오버헤드였습니다.그래도 그만한 가치가 있었어
var printPDF = function () {
//prevent double sending
var sendz = {};
sendz.action = "Print";
sendz.url = "api/Print";
jQuery('<form action="' + sendz.url + '" method="POST">' +
'<input type="hidden" name="action" value="Print" />'+
'<input type="hidden" name="userID" value="'+$scope.user.userID+'" />'+
'<input type="hidden" name="ApiKey" value="' + $scope.user.ApiKey+'" />'+
'</form>').appendTo('body').submit().remove();
}
구성 요소(예: 각도 js 코드):
function getthefile (){
window.location.href='http://localhost:1036/CourseRegConfirm/getfile';
};
언급URL : https://stackoverflow.com/questions/24080018/download-file-from-an-asp-net-web-api-method-using-angularjs
'programing' 카테고리의 다른 글
Angular에서 $log.debug를 설정/해제하는 방법JS (0) | 2023.03.23 |
---|---|
NodeJs 애플리케이션 및 모듈 전체에서 Mongodb에 대한 연결을 적절하게 재사용하는 방법 (0) | 2023.03.23 |
Android에서 요청을 통해 JSON 개체를 전송하는 방법은 무엇입니까? (0) | 2023.03.23 |
스냅샷을 생성할 때 Jest/Enzym ShowlowWrapper가 비어 있습니다. (0) | 2023.03.23 |
스프링 부트 내의 /info 엔드포인트에 프로그래밍 방식으로 추가하는 방법은 무엇입니까? (0) | 2023.03.23 |