从ASP下载文件.. NET Web API方法使用AngularJS
本文关键字:方法 AngularJS API Web ASP 下载 文件 NET | 更新日期: 2023-09-27 18:06:57
在我的Angular JS项目中,我有一个<a>
锚标记,当点击它时,它会向一个返回文件的WebAPI方法发出HTTP GET
请求。
现在,我希望在请求成功后将文件下载给用户。我怎么做呢?
锚标记:
<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) {
// ...
});
}
我的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中-或转换为blob数据URL,由浏览器打开,如果支持在浏览器中查看mime类型,则触发下载对话框。
###Internet Explorer 11支持(修复)注意:Internet Explorer 11不喜欢使用msSaveBlob
功能,如果它有别名-可能是一个安全功能,但更有可能是一个缺陷,所以使用var saveBlob = navigator.msSaveBlob || navigator.webkitSaveBlob ... etc.
来确定可用的saveBlob
支持导致异常;因此,下面的代码现在单独测试navigator.msSaveBlob
。谢谢?微软
// 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
mime头,以便浏览器知道数据格式。
c# WebApi PDF下载全部使用Angular JS认证
Web 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;
}
Angular JS Service
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;
}
都可以
Angular 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>
这将被重构只是分享代码现在希望它能帮助别人,因为它花了我一段时间得到这个工作
对我来说,Web API是Rails和客户端Angular,使用Restangular和filesver .js
Web API
module Api
module V1
class DownloadsController < BaseController
def show
@download = Download.find(params[:id])
send_data @download.blob_data
end
end
end
end