$ httpの投稿からExcelブックをダウンロードするためのアプリケーションをAngular JSで作成しました。
次のコードでは、情報をJSONの形式で渡し、REST $ httpポストを介してサーバーangular Webサービス(Java)に送信します。 WebサービスはJSONの情報を使用して、Excelブックを作成します。 $ http投稿の成功本文内の応答で、そのdata変数内にバイナリデータを取得していますが、それを変換してExcelファイルとしてダウンロードする方法がわかりません。
バイナリをExcelファイルに変換してダウンロードするための解決策を教えてもらえますか?
私のコードは以下のとおりです:
$http({
url: 'myweb.com/myrestService',
method: "POST",
data: json, //this is your json data string
headers: {
'Content-type': 'application/json'
}
}).success(function (data, status, headers, config) {
// Here i'm getting Excel sheet binary datas in 'data'
}).error(function (data, status, headers, config) {
});
これは、blob
を使用して、ブラウザから実際に実行できます。 responseType
およびsuccess
約束のコードに注意してください。
$http({
url: 'your/webservice',
method: "POST",
data: json, //this is your json data string
headers: {
'Content-type': 'application/json'
},
responseType: 'arraybuffer'
}).success(function (data, status, headers, config) {
var blob = new Blob([data], {type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"});
var objectUrl = URL.createObjectURL(blob);
window.open(objectUrl);
}).error(function (data, status, headers, config) {
//upload failed
});
objectUrl
が開きますPHPのサーバー側コードは、次のようにテストしました。 Javaで同様のヘッダーを設定できると確信しています。
$file = "file.xlsx";
header('Content-disposition: attachment; filename='.$file);
header('Content-Length: ' . filesize($file));
header('Content-Transfer-Encoding: binary');
header('Cache-Control: must-revalidate');
header('Pragma: public');
echo json_encode(readfile($file));
ブラウザは、この方法でデータを保存することを難しくしています。良いオプションの1つは、 filesaver.js を使用することです。 saveAs
のクロスブラウザー実装を提供し、上記のsuccess
promiseのコードの一部を置き換える必要があります。
これがあなたのやり方です:
$http({ url: 'your/webservice', method: 'POST', responseType: 'arraybuffer', data: json, //this is your json data string headers: { 'Content-type': 'application/json', 'Accept': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' } }).success(function(data){ var blob = new Blob([data], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' }); saveAs(blob, 'File_Name_With_Some_Unique_Id_Time' + '.xlsx'); }).error(function(){ //Some error log });
ヒント! 「と」を混在させないでください。常に使用するように固執してください。プロの環境では、たとえばjshintなどのjs検証に合格する必要があります。 :)
保存Excelを別のサービスに配置するので、クリーンな構造になり、投稿は独自の適切なサービスになります。私のサンプルが機能しない場合は、JSフィドルを作成できます。次に、完全な例に使用するJSONデータも必要です。
ハッピーコーディング..エドゥアルド
サーバーの応答を配列バッファーとしてダウンロードします。サーバーのコンテンツタイプ(application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
である必要があります)を使用してBlobとして保存します。
var httpPromise = this.$http.post(server, postData, { responseType: 'arraybuffer' });
httpPromise.then(response => this.save(new Blob([response.data],
{ type: response.headers('Content-Type') }), fileName));
Blobをユーザーのデバイスに保存します。
save(blob, fileName) {
if (window.navigator.msSaveOrOpenBlob) { // For IE:
navigator.msSaveBlob(blob, fileName);
} else { // For other browsers:
var link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.download = fileName;
link.click();
window.URL.revokeObjectURL(link.href);
}
}
私のために働いた-
$scope.downloadFile = function () {
Resource.downloadFile().then(function (response) {
var blob = new Blob([response.data], { type: "application/pdf" });
var objectUrl = URL.createObjectURL(blob);
window.open(objectUrl);
},
function (error) {
debugger;
});
};
私のリソースファクトリから次を呼び出します
downloadFile: function () {
var downloadRequst = {
method: 'GET',
url: 'http://localhost/api/downloadFile?fileId=dfckn4niudsifdh.pdf',
headers: {
'Content-Type': "application/pdf",
'Accept': "application/pdf"
},
responseType: 'arraybuffer'
}
return $http(downloadRequst);
}
APIがヘッダーコンテンツタイプも設定していることを確認してください-
response.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/pdf");
response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
Javascriptからブラウザのダウンロードウィンドウをトリガーする方法はありません(私の知る限り)。それを行う唯一の方法は、ファイルをブラウザにストリーミングするURLにブラウザをリダイレクトすることです。
RESTサービスを変更できる場合は、POSTリクエストがバイナリファイルではなく、そのファイルのURLで応答するように変更することで解決できる場合があります。これにより、バイナリデータの代わりにJavascriptでURLが取得され、ブラウザをそのURLにリダイレクトできます。これにより、元のページから移動せずにダウンロードが要求されます。
回答No 5は私のために働いた、同様の問題に直面している開発者への提案。
//////////////////////////////////////////////////////////
//Server side
//////////////////////////////////////////////////////////
imports ***
public class AgentExcelBuilder extends AbstractExcelView {
protected void buildExcelDocument(Map<String, Object> model,
HSSFWorkbook workbook, HttpServletRequest request,
HttpServletResponse response) throws Exception {
//poi code goes here ....
response.setHeader("Cache-Control","must-revalidate");
response.setHeader("Pragma", "public");
response.setHeader("Content-Transfer-Encoding","binary");
response.setHeader("Content-disposition", "attachment; filename=test.xls");
OutputStream output = response.getOutputStream();
workbook.write(output);
System.out.println(workbook.getActiveSheetIndex());
System.out.println(workbook.getNumberOfSheets());
System.out.println(workbook.getNumberOfNames());
output.flush();
output.close();
}//method buildExcelDocument ENDS
//service.js at angular JS code
function getAgentInfoExcel(workgroup,callback){
$http({
url: CONTEXT_PATH+'/rest/getADInfoExcel',
method: "POST",
data: workgroup, //this is your json data string
headers: {
'Content-type': 'application/json'
},
responseType: 'arraybuffer'
}).success(function (data, status, headers, config) {
var blob = new Blob([data], {type: "application/vnd.ms-Excel"});
var objectUrl = URL.createObjectURL(blob);
window.open(objectUrl);
}).error(function (data, status, headers, config) {
console.log('Failed to download Excel')
});
}
////////////////////////////////in .html
<div class="form-group">`enter code here`
<a href="javascript:void(0)" class="fa fa-file-Excel-o"
ng-click="exportToExcel();"> Agent Export</a>
</div>
別のアプローチを採用することもできます。$ httpを使用する必要はなく、追加のライブラリを必要とせず、どのブラウザでも動作するはずです。
ページに非表示のフォームを配置するだけです。
<form name="downloadForm" action="/MyApp/MyFiles/Download" method="post" target="_self">
<input type="hidden" name="value1" value="{{ctrl.value1}}" />
<input type="hidden" name="value2" value="{{ctrl.value2}}" />
</form>
そして、このコードをangularコントローラーに配置します。
ctrl.value1 = 'some value 1';
ctrl.value2 = 'some value 2';
$timeout(function () {
$window.document.forms['downloadForm'].submit();
});
このコードはデータを/ MyApp/MyFiles/Downloadに投稿し、ダウンロードフォルダーにファイルを受け取ります。
Internet Explorer 10で動作します。
従来のHTMLフォームでは複雑なオブジェクトを投稿できない場合、2つのオプションがあります。
1。オブジェクトを文字列化し、文字列としてフォームフィールドのいずれかに配置します。
<input type="hidden" name="myObjJson" value="{{ctrl.myObj | json:0}}" />
2。 HTML JSONフォームを検討してください: https://www.w3.org/TR/html-json-forms/
これを行うサービスを作成しました。
標準の$http
オブジェクトを渡し、いくつかの追加パラメーターを追加します。
1)「タイプ」パラメーター。取得するファイルのタイプを指定します。デフォルト:'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
2)「fileName」パラメーター。これは必須であり、拡張子を含める必要があります。
例:
httpDownloader({
method : 'POST',
url : '--- enter the url that returns a file here ---',
data : ifYouHaveDataEnterItHere,
type : 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', // this is the default
fileName : 'YourFileName.xlsx'
}).then(res => {}).catch(e => {});
必要なのはそれだけです。ファイルは、ポップアップなしでユーザーのデバイスにダウンロードされます。
Gitリポジトリは次のとおりです。 https://github.com/stephengardner/ngHttpDownloader