私は自分のウェブアプリからAndroidモバイルのブラウザを使用してファイルをダウンロードしようとしています(私の場合はSpring MVCを使用していますが、フレームワーク固有ではなく一般的な問題だと思うので、これにも関わらず)。問題は、AndroidデバイスでChromeまたはネイティブブラウザを試してみると、ファイルのダウンロードが終了せず、常に表示されるIn progress
かqueue
、ダウンロードアプリで(Androidのバージョンによっては4.1.1と5.1.1で試してみます)ということです。
私は典型的なhttp-headers
関係を変更しようとしています:Content-Type
、Content-Disposition
インラインまたはアタッチメントを使用Content-Length
して、運がないことを指定します。
重要なのは、WindowsまたはLinuxのデスクトップブラウザでは、いずれの場合もファイルが正しくダウンロードされるということです。
私の試みのいくつか:
使用org.springframework.http.ResponseEntity
:
@RequestMapping(value= {"/evidenciaDownload"},method = RequestMethod.GET)
public ResponseEntity<byte[]> getEvidencia(
@RequestParam(value = "paramsCoded", required = true) String paramsCoded) throws IOException {
String url = configPropsService.getEvidenciaUrlDownload() + URLEncoder.encode(paramsCoded,"UTF-8");
logger.info("[getEvidencia] Recuperem l'evidencia de : " + url);
// bytes are correct
byte[] evidencia = downloadFile(url);
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.set("Content-Type", "application/pdf");
//responseHeaders.set("Content-Disposition","attachment; filename=\"evidencia.pdf\";");
responseHeaders.set("Content-Disposition","inline; filename=evidencia.pdf");
responseHeaders.setContentLength(evidencia.length);
return new ResponseEntity<byte[]>(evidencia, responseHeaders,HttpStatus.CREATED);
}
直接使用してorg.springframework.web.bind.annotation.ResponseBody
ドキュメントを返すためにbytes[]
、そしてproduces = "application/pdf"
上@RequestMapping
:
@RequestMapping(value= {"/evidenciaDownload"},method = RequestMethod.GET, produces = "application/pdf")
public @ResponseBody byte[] getEvidencia(
@RequestParam(value = "paramsCoded", required = true) String paramsCoded) throws IOException {
String url = configPropsService.getEvidenciaUrlDownload() + URLEncoder.encode(paramsCoded,"UTF-8");
logger.info("[getEvidencia] Recuperem l'evidencia de : " + url);
return downloadFile(url);
}
または、javax.servlet.http.HttpServletResponse
出力ストリームにファイルを書き込み、ヘッダーを指定します。
@RequestMapping(value= {"/documentDownload"},method = RequestMethod.GET)
public void getDocument(
@RequestParam(value = "paramsCoded", required = true) String paramsCoded,
HttpServletResponse response) throws IOException {
String url = configPropsService.getDocumentsNotficacioUrlDownload() + URLEncoder.encode(paramsCoded,"UTF-8");
logger.info("[getDocument] Recuperem el document de : " + url);
// bytes are correct
byte[] downloadFile = downloadFile(url);
ServletOutputStream outputStream = response.getOutputStream();
int fileLength = IOUtils.copy(new ByteArrayInputStream(downloadFile), outputStream);
response.setHeader("Content-Disposition","attachment;filename=\"evidencia.pdf\"");
response.setContentLength(fileLength);
response.setContentType("application/pdf");
outputStream.flush();
outputStream.close();
}
私が言ったように、Windows / Linuxのデスクトップブラウザでは3つのケースがうまく機能しますが、AndroidデバイスのChromeやネイティブブラウザではうまく機能しません。
私は自分の問題の原因を見つけるのに時間を費やしているので、答えを投稿します。これが誰かの助けになることを願っています。
この問題は、最終的にWebアプリが展開されているサーバー証明書によって引き起こされます。サーバー証明書は、弱いアルゴリズム(md5)でハッシュされた中間証明書チェーンを持つ運用前の認証局によって発行されます。また、そのCAはプリプロダクションのものであるため、Androidでは信頼されていません。
デスクトップでは、以前にダウンロードしたため、サーバー証明書の問題について警告しているページをスキップしたため、ファイルが正しくダウンロードされます。
アンドロイドでは、少なくともクロームを使用すると、サーバー証明書に関する警告ページも表示され、スキップしますが、ダウンロードマネージャーでは、ファイルはキューに表示されるか、無期限に進行中ですが、エラーメッセージは表示されません。エラーメッセージや何が起こっているのかについての指示がないので、私はこの問題にしばらく時間を費やしています。
最後に、サーバー証明書を変更し、信頼できるCAによって発行された正しい証明書を使用すると、質問で指定された3つのコードアプローチに対してファイルが正しくダウンロードされ始めます。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加