私はAngularJSとSpringを使用してアプリケーションを書いています。サーバーにリクエストを送信し、コントローラーから返されたレスポンスをファイルとしてダウンロードしたいと思います。コントローラーでは、csvファイルの内容(文字列として)、つまり1;2;3;4
(1行、4列)。この応答をファイルとしてダウンロードする最も簡単な方法は何ですか?
以下に、簡単なコードを投稿しました。 Springコントローラーの場合:
@RequestMapping(value = "/csv", method = GET)
@ResponseBody
public String getCsvFile() {
return getCsvContent();
}
JavaScript(AngularJS)で
return $http({method: 'GET', url: 'csv/'});
ヘッダーを設定して(以下)応答ストリームにも書き込もうとしていましたが、クライアント側では、このコンテンツをダウンロードするファイルとしてではなく、常に文字列として取得しています。
@RequestMapping(value = "/csv", method = GET)
@ResponseBody
public void getCsvFile(HttpServletResponse response) {
response.setContentType("application/csv");
response.setHeader("Content-Disposition", "attachment; filename=file.csv");
response.setContentLength(getCsvContent().getBytes().length);
ServletOutputStream out = response.getOutputStream();
out.write(getCsvContent());
out.flush();
out.close();
}
誰かがクライアント側でファイルとして応答をダウンロードするためにコントローラーのメソッドを正しく書く方法を知っていますか?
私はこれを自分で解決し、サーバーから機能するようにしようとしました。できませんでした。代わりに...
@ dnc253の答えを明確にするために、$window.open(URL)
は、Angularアプリケーションが別のウィンドウで特定のURLを開くようにする方法です。これは実際にテスト可能なangularユニバーサルwindow.open()
のプロキシ。これは素晴らしいソリューションであり、履歴を保存し、ファイルをダウンロードし、サポートされている場合は新しいブラウザウィンドウでレンダリングします。信頼性にとって大きな問題であるポップアップブロッカーにアクセスします。ユーザーは、何が起こっているのかを単純に理解していないことが多いため、currentウィンドウでファイルをすぐにダウンロードしてもかまわない場合は、同様に効果的なユニバーサルjavascriptメソッドを使用できます:location.href = "uriString"
、これは私にとって魅力のようです。 Angularは何も起こらなかったことに気づきません。POST/ PUT操作が完了したら、Promiseハンドラーで呼び出します。必要であれば、POST/PUTが呼び出すURLを返すようにします、まだ推測できない場合は、PUT/POSTに応答してダウンロードした場合と同じ動作をユーザーに提供します。例:
$http.post(url, payload).then(function(returnData){
var uriString = parseReturn(returnData);
location.href="uriString"
})
実際には、XHRリクエストから何かを直接ダウンロードできますが、HTML5ファイルAPIを完全にサポートする必要があり、ユーザーが利用できるようにする前にファイルにローカル変換を実行する必要がない限り、通常は価値があります。 。 (残念ながら、私はそれについて詳細を提供する時間が足りませんが、他にSO使用に関する投稿があります。)
XHRリクエストを使用してファイルをダウンロードすることが可能です。 angular $ httpを使用してファイルをロードし、HTML5のBlob機能を使用してブラウザに保存することができます。保存に役立つライブラリがあります。 FileSaver.js 。
あなたがそれを必要とする場合に備えて、ここであなたを助けることができるリンクのカップル:
乾杯
コードサンプルを理解するために、以下のコメントを書きました。私がそれに応じてファイルに名前を付けたので、使用している場合、彼らはそれに従うことができます。
サーバーが応答でblobを送信している場合、クライアントはそれを生成できるはずです。
私の目的はこれらを使用することで解決されます。 type: 'application/*'をすべてのファイルに使用したため、ファイルをダウンロードできます。
作成された「downloadLink」変数は、応答で使用される手法であるため、リンクをクリックしたように入力され、応答が来て、そのhrefがトリガーされます。
controller.js
//this function is in controller, which will be trigered on download button hit.
$scope.downloadSampleFile = function() {
//create sample hidden link in document, to accept Blob returned in the response from back end
var downloadLink = document.createElement("a");
document.body.appendChild(downloadLink);
downloadLink.style = "display: none";
//This service is written Below how does it work, by aceepting necessary params
downloadFile.downloadfile(data).then(function (result) {
var fName = result.filename;
var file = new Blob([result.data], {type: 'application/*'});
var fileURL = (window.URL || window.webkitURL).createObjectURL(file);
//Blob, client side object created to with holding browser specific download popup, on the URL created with the help of window obj.
downloadLink.href = fileURL;
downloadLink.download = fName;
downloadLink.click();
});
};
services.js
.factory('downloadFile', ["$http", function ($http) {
return {
downloadfile : function () {
return $http.get(//here server endpoint to which you want to hit the request
, {
responseType: 'arraybuffer',
params: {
//Required params
},
}).then(function (response, status, headers, config) {
return response;
});
},
};
}])
// Java PART
@RequestMapping(value = "/report-Excel", method = RequestMethod.GET)
public ResponseEntity<byte[]> getReportExcel(@RequestParam("bookingStatusType") String bookingStatusType,
@RequestParam("endDate") String endDate, @RequestParam("product") String product, @RequestParam("startDate") String startDate)throws IOException, ParseException {
//Generate Excel from DTO using any logic after that do the following
byte[] body = wb.getBytes();
HttpHeaders header = new HttpHeaders();
header.setContentType(new MediaType("application", "xlsx"));
header.set("Content-Disposition", "inline; filename=" + fileName);
header.setCacheControl("must-revalidate, post-check=0, pre-check=0");
header.setContentLength(body.length);
return new ResponseEntity<byte[]>(body, header, HttpStatus.OK);
}
//HTML PART
<html>
<head>
<title>Test</title>
<meta http-equiv="content-type" content="application/x-www-form-urlencoded; charset=UTF-8">
</head>
<body>
<form name="downloadXLS" method="get" action="http://localhost:8080/rest/report-Excel" enctype="multipart/form-data">
<input type="text" name="bookingStatusType" value="SALES"></input>
<input type="text" name="endDate" value="abcd"></input>
<input type="text" name="product" value="FLIGHT"></input>
<input type="text" name="startDate" value="abcd"></input>
<input onclick="document.downloadXLS.submit()" value="Submit"></input>
</form>
</body>
</html>
それは私のために働いています:
スプリングコントローラー:DownloadController.Java
package com.mycompany.myapp.controller;
import Java.io.File;
import Java.io.FileInputStream;
import Java.io.IOException;
import Java.io.InputStream;
import Java.io.OutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.Apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.mycompany.myapp.exception.TechnicalException;
@RestController
public class DownloadController {
private final Logger log = LoggerFactory.getLogger(DownloadController.class);
@RequestMapping(value = "/download", method = RequestMethod.GET)
public void download(@RequestParam ("name") String name, final HttpServletRequest request, final HttpServletResponse response) throws TechnicalException {
log.trace("name : {}", name);
File file = new File ("src/main/resources/" + name);
log.trace("Write response...");
try (InputStream fileInputStream = new FileInputStream(file);
OutputStream output = response.getOutputStream();) {
response.reset();
response.setContentType("application/octet-stream");
response.setContentLength((int) (file.length()));
response.setHeader("Content-Disposition", "attachment; filename=\"" + file.getName() + "\"");
IOUtils.copyLarge(fileInputStream, output);
output.flush();
} catch (IOException e) {
log.error(e.getMessage(), e);
}
}
}
AngularJsサービス:download.service.js
(function() {
'use strict';
var downloadModule = angular.module('components.donwload', []);
downloadModule.factory('downloadService', ['$q', '$timeout', '$window',
function($q, $timeout, $window) {
return {
download: function(name) {
var defer = $q.defer();
$timeout(function() {
$window.location = 'download?name=' + name;
}, 1000)
.then(function() {
defer.resolve('success');
}, function() {
defer.reject('error');
});
return defer.promise;
}
};
}
]);
})();
AngularJs config:app.js
(function() {
'use strict';
var myApp = angular.module('myApp', ['components.donwload']);
/* myApp.config([function () {
}]);
myApp.run([function () {
}]);*/
})();
AngularJsコントローラー:download.controller.js
(function() {
'use strict';
angular.module('myApp')
.controller('DownloadSampleCtrl', ['downloadService', function(downloadService) {
this.download = function(fileName) {
downloadService.download(fileName)
.then(function(success) {
console.log('success : ' + success);
}, function(error) {
console.log('error : ' + error);
});
};
}]);
})();
index.html
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<title>My App</title>
<link rel="stylesheet" href="bower_components/normalize.css/normalize.css" />
<link rel="stylesheet" href="assets/styles/main.css" />
<link rel="icon" href="favicon.ico">
</head>
<body>
<div ng-controller="DownloadSampleCtrl as ctrl">
<button ng-click="ctrl.download('fileName.txt')">Download</button>
</div>
<script src="bower_components/angular/angular.min.js"></script>
<!-- App config -->
<script src="scripts/app/app.js"></script>
<!-- Download Feature -->
<script src="scripts/app/download/download.controller.js"></script>
<!-- Components -->
<script src="scripts/components/download/download.service.js"></script>
</body>
</html>