質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

1回答

6026閲覧

poiにおいて、Excelダウンロード処理を関数内で実行すると、ダウンロード後のタブが自動で閉じられない

退会済みユーザー

退会済みユーザー

総合スコア0

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

0グッド

0クリップ

投稿2016/06/13 13:41

編集2016/06/14 01:52

PoiでExcelのダウンロードを行っているのですが、

以下のようにサーブレット側、サーブレットから呼び出される関数を作ると、
ダウンロード処理完了後に自動でタブが閉じられません。

Java

1 2 protected void doDownload(HttpServletResponse response) { 3 4 response.setContentType("application/octet-stream"); 5 String fileName = null; 6 try { 7 fileName = new String(getExcelFileName().getBytes("Windows-31J"), "ISO-8859-1"); 8 } catch (UnsupportedEncodingException e1) { 9 e1.printStackTrace(); 10 } 11 response.setHeader("Content-Disposition", "attachments; filename=\"" + fileName + "\""); 12 response.setHeader("Cache-Control", "public"); 13 response.setHeader("Pragma", "public"); 14 15 try { 16 OutputStream out = new BufferedOutputStream(response.getOutputStream()); 17 wb.write(out); 18 } catch (IOException e) { 19 e.printstactrace(); 20 } finally { 21 try { 22 wb.close(); 23 } catch (IOException e) { 24 e.printstactrace(); 25 } 26 } 27 } 28

Java

1 protected void doUpdateExcel(HttpServletRequest request, HttpServletResponse response) 2 throws ServletException, IOException { 3 4 --- エクセルを生成する処理 --- 5 6 doDownload(); // ここで上記のエクセルダウンロードを呼び出すと、タブが自動で閉じられない 7 8}

一方、関数を使わずに、関数の処理をそっくりそのまま、サーブレットで実行すれば、
タブは自動で閉じられます。

おそらく原因は、関数内で、wb.write(out)を行うと、この内部処理でreturnするような処理になっていると思うのですが、
関数でそれを実行すると、まだ、サーブレット側の処理がのこっていることになり、
一方、サーブレットでwb.write(out)とすれば、内部処理でreturn後、サーブレットがおわることになり、
タブが自動に閉じられるような挙動になっているのではと思っています。

同じコードをサーブレット単位で書くのは面倒なので、
関数内で実行したいですが、なにかよい方法はございませんでしょうか。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

argius

2016/06/13 15:02

すみません、「wb.outを関数内でコードを組むと」とありますが、掲載いただいたコードには実際にダウンロードデータを出力する部分が書かれていないため、問題となる処理がどう書かれているのかが分かりません。できれば、「servlet側でwb.out」「wb.outを関数内で」の違いが分かるように記載していだたけないでしょうか。
guest

回答1

0

ベストアンサー

記載されているコードが完全に動作するものでないので、推測になってしまいますが、
普通に書いていれば、特にメソッドに分けたところでタブが閉じないという現象は
発生しないと思います。
実際に書いてみて確認しています。

new XSSFWorkbook()の処理が登場していないので、
メソッドに分けたときとそうでないときでXSSFWorkbookの処理の仕方が
違っている疑いもありますが、実際に見てみないと分かりません。

あとは、エラーが発生した場合に動作が変わる可能性もあるかも知れません。
printStackTrace()の情報が何かログかコンソールに出ていませんか?

ブラウザーの種類やHTML側の処理にもよるかもしれません。
ChromeとFirefoxでaタグのtarget="_blank"にしてタブを開いてダウンロードさせてみましたが、
タブが閉じないというのは確認できませんでした。


(追記)

検証したコードです。

アプリケーションサーバーはTomcat8です。

lang

1// import省略 2 3@WebServlet("/servlet1") 4public final class Servlet1 extends HttpServlet { 5 private static final long serialVersionUID = 1L; 6 7 @Override 8 protected void doGet(HttpServletRequest req, HttpServletResponse response) throws ServletException, IOException { 9 doUpdateExcel(req, response); 10 System.out.println("end of doGet"); // ダウンロード後に出力される 11 } 12 13 protected void doDownload(HttpServletResponse response) throws IOException { 14 response.setContentType("application/octet-stream"); 15 String fileName = null; 16 try { 17 fileName = new String(getExcelFileName().getBytes("Windows-31J"), "ISO-8859-1"); 18 } catch (UnsupportedEncodingException e1) { 19 e1.printStackTrace(); 20 } 21 response.setHeader("Content-Disposition", "attachments; filename=\"" + fileName + "\""); 22 response.setHeader("Cache-Control", "public"); 23 response.setHeader("Pragma", "public"); 24 25 // どうやって作っているか分からないのでとりあえずローカルのファイルを開く 26 Workbook wb = new XSSFWorkbook("../" + getExcelFileName()); 27 try { 28 OutputStream out = new BufferedOutputStream(response.getOutputStream()); 29 wb.write(out); 30 } catch (IOException e) { 31 e.printStackTrace(); 32 } finally { 33 try { 34 wb.close(); 35 } catch (IOException e) { 36 e.printStackTrace(); 37 } 38 } 39 } 40 41 protected void doUpdateExcel(HttpServletRequest request, HttpServletResponse response) throws ServletException, 42 IOException { 43 // --- エクセルを生成する処理 --- 44 45 doDownload(response); // ここで上記のエクセルダウンロードを呼び出すと、タブが自動で閉じられない 46 47 } 48 49 private String getExcelFileName() { 50 return "dltest.xlsx"; 51 } 52 53}

投稿2016/06/14 04:04

編集2016/06/14 05:42
argius

総合スコア9388

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2016/06/14 04:23

お言葉を返すようですが、関数化してしまうと、wb.writeのリターンを関数で拾ってしまうのが、普通と思います。 ちなみに、関数にして、タブが閉じたコードを記載いただいてもよいでしょうか。
argius

2016/06/14 05:42

回答欄に追記しました。
退会済みユーザー

退会済みユーザー

2016/06/14 08:42

ご回答ありがとうございました。 おかげ様で無事解決できました。 原因は、new XSSFWorkbook()の際の引数をString型のパスに変更したところ、 関数内でも動作するようになりました。 具体的には以下のようにです。 ``` InputStream is = getServletContext().getResourceAsStream(getExcelFileName()); wb = new XSSFWorkbook(is); ``` ご提示いただいた以下に変更しまして、出力されました。 ``` Workbook wb = new XSSFWorkbook("../" + getExcelFileName()); ``` ご対応感謝致します。
argius

2016/06/14 09:11

"../"にしたのは記載が無かったためとりあえず書いたものなので、 そのまま採用しない方が良いかも知れません。 ファイルの相対位置が分かっていれば、 元のgetServletContext().getResourceAsStreamでも取得は可能です。 この場合はコンテキストルートからの相対位置になります。 どこにExcelファイルがあるのか分からないのであれば、 ファイルの位置については確認しておいたほうが良いと思います。 下記のコードをどこでも良いですがnew XSSFWorkbookの前あたりにでも 書いて実行すると分かります。 System.out.println("カレントディレクトリー: " + new java.io.File("./").getAbsolutePath()); 相対パスにした場合、環境の違いによって、 「テスト環境では上手く行くけれど、本番環境では上手く行かない」 のようなことが起こる可能性があるので注意が必要です。 (書き込み許可が無いかも知れない、など)
退会済みユーザー

退会済みユーザー

2016/06/15 04:36

ご回答ありがとうございます。 勉強になります。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問