18
22

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

クロスブラウザ対応の日本語ファイルのダウンロード on Spring MVC

Last updated at Posted at 2016-06-27

日本語を含むマルチバイトで構成されるファイル名のダウンロードを、Spring MVCで実装してみました。ポイントは、ファイル名のURLエンコーディングの要否なのですが、これはブラウザによって扱いが違うのが厄介です。困ったな〜と思ってググっていたら・・・「filename」と「filename*」を使えばいいよ!というブログをみつけました。

動作検証バージョン

  • Spring Boot 1.3.5.RELEASE
  • Spring Framework 4.2.6.RELEASE

Handlerメソッドの実装

細かい説明はしませんが、Handlerメソッドはこんな感じ。

@Autowired
DownloadSupport downloadSupport;

@RequestMapping(path = "/mocks/{id}/file", method = RequestMethod.GET)
public ResponseEntity<Resource> download(@PathVariable int id) throws UnsupportedEncodingException {
    MockResponse mockResponse = service.findOne(id); // ファイル名とダウンロードデータ(BLOBデータ)はDBから取得
    HttpHeaders headers = new HttpHeaders();
    downloadSupport.addContentDisposition(headers, mockResponse.getFileName()); // サポートクラスをみてね!
    return ResponseEntity
            .status(HttpStatus.OK)
            .contentType(MediaType.APPLICATION_OCTET_STREAM)
            .headers(headers)
            .body(new InputStreamResource(mockResponse.getBody()));
}

Supportクラスの実装

Content-Dispositionヘッダを作成するサポートクラスをこんな感じでつくる。「filename」にファイル名、「filename*」にURLエンコーディング後のファイル名を設定します。こうすることで、クロスブラウザ対応できてしまう(ようです)!!

import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Component;
import org.springframework.web.util.UriUtils;

import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;

@Component
public class DownloadSupport {

    private static final String CONTENT_DISPOSITION_FORMAT = "attachment; filename=\"%s\"; filename*=UTF-8''%s";

    public void addContentDisposition(HttpHeaders headers, String fileName) throws UnsupportedEncodingException {
        String headerValue = String.format(CONTENT_DISPOSITION_FORMAT,
                fileName, UriUtils.encode(fileName, StandardCharsets.UTF_8.name()));
        headers.add(HttpHeaders.CONTENT_DISPOSITION, headerValue);
    }

}

ブログではJava SEのURLEncoderを使っていましたが、半角スペースが「+」になっちゃったので、Springが提供しているorg.springframework.web.util.UriUtilsを使ってエンコーディングしていますが、これが正しいのかはちゃんと調べてないので、悪しからず。。。。 :sweat_smile:

とりあえず・・・・

  • Chrome 51.0.2704.103 (64-bit) on Mac
  • Firefox 47.0 on Mac
  • Safari 8.0.8 (10600.8.9) on Mac
  • IE 11 on Windows 10
  • Edge 25 on Window 10

上では、それっぽく動きました。

まとめ

ブラウザのバージョンによっても対応状況が変わりそうな気はしますが・・・、対応するブラウザだけをサポートすればOKなら、この方法で対応するのがよさげです。

参考サイト

18
22
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
18
22

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?