LoginSignup
14
12

More than 5 years have passed since last update.

エクセルをダウンロードするサーブレットのサンプル。

Last updated at Posted at 2016-12-25

エクセルがダウンロードできるサーブレットを作成する機会があり、なかなかにはまったので、そのサンプルを残しておきたいと思います。なおJavaからエクセルを操作するにあたってはApache POIを利用していますが、その導入方法や使用方法については省略しています。

まずはServletクラスを以下のように作成します。

package servlet;

import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

/**
 * エクセルをダウンロードするサーブレット。
 * @author nekoTheShadow
 *
 */
@WebServlet("/download")
public class ExcelDownloadServlet extends HttpServlet {

    /**
     * ダウンロードページを表示する。
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.getRequestDispatcher("/WEB-INF/jsp/download.jsp").forward(request, response);
    }

    /**
     * POSTされたフォームデータに基づきエクセルを生成し、ダウンロードさせる。
     * @throws UnsupportedEncodingException
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws UnsupportedEncodingException {

        // リクエストの文字コードをUTF-8に変換する。
        request.setCharacterEncoding("UTF-8");

        // リクエストクエリを取得する。
        String param1 = (String) request.getParameter("param1");
        String param2 = (String) request.getParameter("param2");
        String param3 = (String) request.getParameter("param3");

        // ファイル名を生成する: ファイル名はダウンロード日付とする。
        SimpleDateFormat simpleDataFormat = new SimpleDateFormat("yyyy-MM-dd");
        String filename = simpleDataFormat.format(new Date()) + ".xlsx";

        // レスポンスヘッダを設定する。
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setHeader("content-disposition", String.format("attachment; filename=\"%s\"", filename));
        response.setCharacterEncoding("UTF-8");

        // ワークブックとバイトストリーム(レスポンス)を生成する。
        // このふたつはcloseが必ず必要 => try-with-resource文を活用する、
        try (Workbook workbook = new XSSFWorkbook();
             OutputStream outputStream = response.getOutputStream()) {

            // シートを生成する: 実際は複雑なロジックを用いるが、今回はサンプルなのでシンプルなものにとどめておく。
            Sheet sheet = workbook.createSheet();
            sheet.createRow(1).createCell(1).setCellValue(param1);
            sheet.createRow(2).createCell(1).setCellValue(param2);
            sheet.createRow(3).createCell(1).setCellValue(param3);

            // ワークブックをレスポンスに出力する。
            workbook.write(outputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }


}

次にdownloadにアクセスした際に表示されるdownload.jspは次の通りです。これは/WEB-INF/jspディレクトリの直下に配置します。

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
    <h1>Excel Download</h1>
    <form method="post" action="/excel/download">
        <p><label>パラメタ1:</label><input type="text" name="param1" /></p>
        <p><label>パラメタ2:</label><input type="text" name="param2" /></p>
        <p><label>パラメタ3:</label><input type="text" name="param3" /></p>

        <p><input type="submit" value="Download Excel" /></p>
    </form>
</body>
</html>

必要なファイルを準備した後はデプロイし、/downloadにアクセスすると次のようなページが現れるはずです。

init.PNG

あとはパラメタを入力してDownload Excelを押下すると、タイトルが日付となったエクセルファイルがダウンロードされます。

image

そして実際にダウンロードしたエクセルファイルを開いてみると、とりわけ壊れたりなどせず、ちゃんとエクセルファイルが作られていることがわかります。

excel.PNG

今回特に重要なのはレスポンスヘッダの設定でしょうか。content-typeに指定したapplication/vnd.openxmlformats-officedocument.spreadsheetml.sheetは正直なところあまり見かけないものですし、そもそもcontent-dispositionという属性自体が個人的にはなじみが薄く、はまったポイントでした。

// レスポンスヘッダを設定する。
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setHeader("content-disposition", String.format("attachment; filename=\"%s\"", filename));
response.setCharacterEncoding("UTF-8");
14
12
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
14
12