使用 ANGULARJS 从 Jersey rest api 调用中下载/保存文件。文件附加响应为“Content-Disposition”
Posted
技术标签:
【中文标题】使用 ANGULARJS 从 Jersey rest api 调用中下载/保存文件。文件附加响应为“Content-Disposition”【英文标题】:File download/save from a Jersey rest api call using ANGULARJS . file is attached with response as "Content-Disposition" 【发布时间】:2016-01-19 14:11:54 【问题描述】:我是 Angular 的新手。我有 java rest api,它返回 CSV 文件作为附件作为响应 | “内容处置”,“附件;文件名=”|内容类型 :application/octet-stream
现在,当我使用 $http 从 AngularJS 调用这个 api 时,我得到 response.data =""(空白)
我正在使用基本授权来确保安全,因此我必须在调用 API 时传递标头,因此无法使用链接单击或从 CSV 下载打开新窗口。
测试我何时删除授权并在浏览器中点击 url,然后下载 CSV 文件。所以在服务器端没有问题。
我需要 angularjs 方面的帮助才能从 web api 响应中下载 CSV 文件作为附件。
这是我的 Java API 代码
public class ServiceAPI
@GET
@Produces(MediaType.APPLICATION_OCTET_STREAM)
public Response getFileAsCSVFile()
byte[] file=null;
try
ArrayList<> List=new ArrayList<>();// data retrieved from DB
if(null != List)
file=convertJsonToCSV(new Gson().toJson(List));
catch (ParseException e)
e.printStackTrace();
catch (IOException e)
// TODO Auto-generated catch block
e.printStackTrace();
return Response.ok(getBytes(file),MediaType.APPLICATION_OCTET_STREAM).header("Content-Disposition", "attachment; filename=" + "FileName.csv").build();
和 Angular 代码:
app.controller('review', ['$scope', '$http', function ($scope, $http)
$scope.fromDate = new Date();
$scope.toDate = new Date();
$scope.minDate = new Date(
$scope.fromDate.getFullYear(),
$scope.fromDate.getMonth() - 2,
$scope.fromDate.getDate(),
$scope.toDate.getFullYear(),
$scope.toDate.getMonth() - 2,
$scope.toDate.getDate()
);
$scope.maxDate = new Date(
$scope.fromDate.getFullYear(),
$scope.fromDate.getMonth() - 2,
$scope.fromDate.getDate(),
$scope.toDate.getFullYear(),
$scope.toDate.getMonth() - 2,
$scope.toDate.getDate()
);
$scope.reviews = json;
function openSaveAsDialog(filename, content, mediaType)
var blob = new Blob([content], type: mediaType);
saveAs(blob, filename);
function callApi(url)
// var dat=apiFactory.getServiceData(url);
// console.log(dat);
// apiFactory.getServiceData(url);
var responseType='arraybuffer';
var expectedMediaType='application/octet-stream';
$http.get(url,
headers:
accept: expectedMediaType
,
responseType:responseType,
cache: true,
transformResponse: function (data)
var pdf;
if (data)
pdf = new Blob([data],
type: expectedMediaType
);
return
response: pdf
;
).then(function (data,status,headers)
var filename='Preview.csv',
octetStreamMime = "application/octet-stream",
contentType;
headers = data.headers();
contentType = headers["content-type"] || octetStreamMime;
// openSaveAsDialog(filename, response.data, expectedMediaType);
if (navigator.msSaveBlob)
var blob = new Blob([data], type: contentType );
navigator.msSaveBlob(blob, filename);
else
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)
// Prepare a blob URL
var blob = new Blob([data.data], type: contentType );
var url = urlCreator.createObjectURL(blob);
link.setAttribute("href", url);
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);
else
// Prepare a blob URL
// Use application/octet-stream when using window.location to force download
var blob = new Blob([data], type: octetStreamMime );
var url = urlCreator.createObjectURL(blob);
$window.location = url;
);
;
$scope.submit = function (fromDate, toDate)
$scope.url = API_url;
var resp =callApi(($scope.url).split(" ").join("%20"));
console.log(resp);
;
,
]);
【问题讨论】:
【参考方案1】:我有一个使用 spring MVC 而不是 JAX-RS (Jersey) 的示例
HTML:
<button ng-click="downloadPdf()" class="btn btn-primary">download PDF</button>
Angularjs 控制器:
$scope.downloadCsv = function ()
console.log("downloadCsv");
var fileName = "test.csv";
var a = document.createElement("a");
document.body.appendChild(a);
XxxxxxServiceCSV.downloadCsv().then(function (result)
console.log("downloadCsv callback");
var file = new Blob([result.data], type: 'application/csv');
var fileURL = URL.createObjectURL(file);
a.href = fileURL;
a.download = fileName;
a.click();
);
;
Angularjs 服务:
angular.module('xxxxxxxxApp')
.factory('XxxxxxServiceCSV', function ($http)
return
downloadCsv: function ()
return $http.get('api/downloadCSV', responseType: 'arraybuffer' ).then(function (response)
return response;
);
;
);
Java 代码 JAX-RS(spring MVC):
@RequestMapping(value = "/downloadCSV", method = RequestMethod.GET, produces = "application/csv")
public void demo(HttpServletResponse response) throws IOException
List<String> names = new ArrayList<String>();
names.add("First Name");
names.add("Second Name");
names.add("Third Name");
names.add("Fourth Name");
BufferedWriter writer = new BufferedWriter(response.getWriter());
try
response.setHeader("Content-Disposition", "attachment; filename=\"test.csv\"");
for (String name : names)
writer.write(name);
writer.write(",");
writer.newLine();
catch (IOException ex)
finally
writer.flush();
writer.close();
【讨论】:
使用 JAX-RS(Jersey):@Produces(MediaType.TEXT_PLAIN) 或 @Produces("text/csv") 谢谢哥们...它就像魅力一样...节省了我的时间:) 可以在 JAX-RS(Jersey) 中使用@POST 方法吗以上是关于使用 ANGULARJS 从 Jersey rest api 调用中下载/保存文件。文件附加响应为“Content-Disposition”的主要内容,如果未能解决你的问题,请参考以下文章
使用 Spring Security、Jersey 和 AngularJS 验证表单
AngularJS + Jersey RESTful 后端:身份验证和授权
AngularJS $http、CORS 和 Jersey 的基本身份验证
前端Angularjs +后端Jersey REST Services +需要设置开发环境