保存ダイアログを表示させてファイルをダウンロードさせる方法

公開日: : Java

例えば、ブラウザに表示している画像は右クリックを使ってダウンロードできますが、左クリックから保存ダイアログを使ってダウンロードさせることもできます。

画像の大きさをリサイズするサービス Resizer では、この方法でリサイズした画像をダウンロードさせています。

この方法の実装方法をメモしておきます。

icatch-10139609144_5bc33706f9_z

photo credit: All rights reserved by Dell’s Official Flickr Page

目次

1. レスポンスのコンテントタイプとヘッダを設定する

画像や zip などのコンテンツをダウンロードさせるには、コンテントタイプ(Content-Type)に “application/octet-stream” を設定したレスポンスを返してやります。

“application/octet-stream” が設定されていると、多くのブラウザは「このコンテンツをダウンロードしますか?」とダイアログを表示させる実装になっているそうです。
なので、この仕組みを使ってコンテンツを自分のマシンにとり込んでしまうというわけです。

項目はコンテントタイプ以外にもヘッダに次のものを設定します。

  • コンテンツの名称
  • コンテンツのサイズ(容量)

コンテンツの名称はたいていの場合ファイル名になると思います。
ダウンロードさせる画像ファイルや zip ファイルなどの名称をそのまま設定すれば OK です。

コンテンツのサイズはダウンロードさせるコンテンツの容量になります。
単位はバイトです。

2. Java によるサンプルソースコード

Java でこの処理を行うサンプルを書いてみました。
他の言語でもやることは変わらないと思うので、参考にはなるんじゃないかと思います。

/**
 * コンテンツ({@code File} オブジェクト)をダウンロードする。
 * 
 * @param response コンテンツをダウンロードするのに使用する {@code HttpServletResponse} オブジェクト
 * @param file ダウンロードするコンテンツを格納した {@code File} オブジェクト
 * @throws FileNotFoundException 画像ファイルが存在しなかった場合
 * @throws IOException 画像ファイルの読み書きに失敗した場合
 */
public void download(HttpServletResponse response, File file) throws FileNotFoundException, IOException {
    setUpResponseForDownload(response, file);

    copyFileToResponse(response, new FileInputStream(file));
}

/**
 * コンテンツをダウンロードする際のレスポンスを設定する。
 * 
 * 次をレスポンスとヘッダに設定する。
 * 
 * <ul>
 * <li>ContentType に "application/octet-stream" を設定</li>
 * <li>Header にコンテンツの名称を設定</li>
 * <li>Header にコンテンツのサイズ(容量)を設定</li>
 * </ul>
 * 
 * @param response コンテンツをダウンロードするのに使用する {@code HttpServletResponse} オブジェクト
 * @param file ダウンロードするコンテンツを格納した {@code File} オブジェクト
 */
private void setUpResponseForDownload(HttpServletResponse response, File file) {
    response.setContentType("application/octet-stream");
    response.setHeader("Content-Disposition", "attachment; filename=\"" + file.getName() + "\"");
    response.setHeader("Content-Length", String.valueOf(FileUtils.sizeOf(file)));
}

/**
 * コンテンツをレスポンスに設定する。
 * 
 * @param response コンテンツをダウンロードするのに使用する {@code HttpServletResponse} オブジェクト
 * @param inputStream ダウンロードするコンテンツの {@code InputStream} オブジェクト
 * @throws FileNotFoundException 画像ファイルが存在しなかった場合
 * @throws IOException 画像ファイルの読み書きに失敗した場合
 */
private void copyFileToResponse(HttpServletResponse response,
        InputStream inputStream) throws IOException, FileNotFoundException {
    IOUtils.copy(inputStream, response.getOutputStream());
}

コンテンツのサイズ(容量)を計算する方法として Commons IOFileUtils#sizeOf メソッドを使っています。

同様に、コンテンツをレスポンスにセットする方法として [IOUtils#copy](http://commons.apache.org/proper/commons-io/javadocs/api-2.4/org/apache/commons/io/IOUtils.html#copy(java.io.InputStream, java.io.OutputStream)) メソッドを使っています。

Commons IO には、ファイルを扱う際のちょっとした処理がたくさん定義されています。
工数を削減するためにも、どういうものが用意されているのか一度ざっと見ておくことをおすすめします。

3. まとめ

保存ダイアログを表示してファイル(コンテンツ)をダウンロードさせる方法のまとめです。

  • コンテントタイプに “application/octet-stream” を設定する
  • ヘッダにコンテンツの名称を設定する
  • ヘッダにコンテンツのサイズ(容量)を設定する

Googleアドセンス用(PC)

  • このエントリーをはてなブックマークに追加
  • follow us in feedly

関連記事

icatch_4610898091-resized

Java8 の Optional とガード節

メソッドの冒頭で条件チェックを行い、条件を満たしていない場合はさっさと return してしまう「ガ

記事を読む

no image

画像ファイルを選別するFilenameFilter

画像ファイルのみアップロードを許可する仕様があって、何てことはないがフィルターを作って対応したのでメ

記事を読む

GradleLogoReg

Gradle で Java アプリのプロジェクトを作成して Eclipse にインポートするまでの手順

Mac に SDKMAN! を使って Gradle をインストールしたので、実際にプロジェクトを作成

記事を読む

medium_182531101

ClassLoader を使って getResourceAsStream で取得したファイルを UTF-8 で読み込む

よく使う割には覚えられず毎回調べている気がするので備忘録としてメモしておきます。 文字コードを指定し

記事を読む

GradleLogoReg

SDKMAN!(GVM) を使って Mac に Gradle をインストールする

長らく Java のアプリ開発には Maven を使ってきたが、時代に取り残されている感じがするので

記事を読む

icatch-zip_524574337_mini-thumbnail

Java でファイルが1つだけ圧縮された zip を解凍するサンプル

ファイルが1つだけ圧縮された zip を解凍するサンプルです。 単一ファイルが圧縮された zip

記事を読む

no image

google-gson でシリアライズ・デシリアライズしたサンプル

これまで Java で JSON を扱うときは JSONIC を使っていたが、google-gson

記事を読む

medium_2055608272

指定した年月の日付を Calendar オブジェクトの一覧で取得する

小ワザです。 業務で、指定した年月の日付を Calendar オブジェクトの一覧で取得する必要があり

記事を読む

icatch_2185253176-resized

Java8 の Optional 型を返す Generics を使ったメソッドを定義する

Java8 の Optional とガード節 に続いて Java8 の Optional ネタ。今回

記事を読む

icatch-thumbnail

レスポンスにサムネイル画像を返す API のサンプル

今回は直接 ImageMagick は関係ありませんが、また画像ネタです。この辺りのことを仕事で扱っ

記事を読む

Googleアドセンス用(PC)

Message

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です


二 × = 10

次のHTML タグと属性が使えます: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Googleアドセンス用(PC)

icatch-jersey_multi_pathparams
Jerseyの@PathParamはスラッシュの間に複数指定できる

http://hoge-api/user/{id}.{format}

icatch-vagrant_box_customize
VagrantのBoxファイルをカスタマイズして独自のBoxファイルを作成する

配布されている Vagrant の Box ファイルを使って検証環境を

icatch-2015-006-1
バリデーションチェックにJava8のOptionalを使ってスマートに書く(自分比)

Web アプリのバリデーションチェックにアノテーションを使うことが増え

icatch-2015-005-1
ユニットテストの偏りを防ぐ命名規則の付け方

ユニットテスト名に以下の命名規則を付けるようにして二ヶ月ぐらい経った。

icatch-2015-004-1
Vagrantで起動したCentOS上のOctopressをホストOSから確認する設定

タイトルの通りだが、Vagrant を使って起動した CentOS に

→もっと見る

PAGE TOP ↑