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

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

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

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

Q&A

解決済

1回答

6239閲覧

ファイルダウンロード処理で例外「getWriter()はこのレスポンスに対して既に呼び出されています」

bluescat

総合スコア16

Java

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

0グッド

0クリップ

投稿2019/02/22 09:06

編集2019/02/25 01:14

いつもお世話になります。
初歩的なことかもしれませんが、行き詰ってしまったので質問させてください。

画面からボタンを押したときにajax通信でJava側の処理を呼び出して
ファイルをダウンロードする処理を実装しているのですが、
「resp_.getOutputStream();」を実行したときに下記例外が発生してしまいます。

java.lang.IllegalStateException: getWriter()はこのレスポンスに対して既に呼び出されています

関連の質問を確認したところ、

一回のコネクションでgetWriterかgetOutputStreamのどちらしか選択できない

と記載されていたので、リソースを解放してあげればよいのだと思うのですが、
例外発生行の直前で「res.getWriter().close();」を入れても、今度はその行で同様の例外が発生するようでした。
※res:HttpServletResponseの変数

リソースを解放する方法についてご教示いただけないでしょうか。

Java8、Tomcat7です。

【参考にした記事】
https://hiyokko-se.com/java_filedownload

【関連の質問】
https://teratail.com/questions/115888

javascript

1$(document).ready(function(){ 2 $('#monthry_report_result_10051').on('click', function(){ 3 var ajaxUrl = '/<コンテキスト名>/xxx/ajax/MonthryReportServices/printMonthryReport'; 4 var param = { code : 10051, title : 'リスト' }; 5 var callbackFunc = function(html){ 6 if($(html).hasClass('error')){ 7 $('.ajaxError').html($(html)); 8 }else{ 9 isDisabled = false; 10 } 11 } 12 ajaxFunc.ajax('post','html', ajaxUrl, param, callbackFunc); 13 }); 14}); 15

javascript

1/*非同期通信用*/ 2var ajaxFunc = { 3 ajax : function(type, dataType, url, data, successFunc, errorFunc, traditional, async){ 4 if(traditional=="undefined") traditional = false; 5 if(async=="undefined") async = true; 6 var xhr = $.ajax({ 7 type : type, 8 url : url, 9 data : data, 10 dataType : dataType, 11 cache : false, 12 timeout : 60000, 13 scriptCharset : "UTF-8", 14 traditional : traditional, 15 async : async, 16 success : function(data){ 17 if(dataType=="json" && data!=null && eval(data).ajaxErrorCode!=null){ 18 var setting = eval(data); 19 AjaxFunc.ajaxError(setting); 20 }else if((dataType=="" || dataType=="html" || dataType=="text") && data.match(/ajaxErrorCode/)!=null){ 21 var setting = eval("("+data+")"); 22 AjaxFunc.ajaxError(setting); 23 }else{ 24 if (successFunc) { 25 if (typeof successFunc == 'string') { 26 eval(successFunc); 27 } else if (typeof successFunc == 'function') { 28 successFunc(data); 29 } 30 } 31 } 32 } 33}

Java

1// ajaxから呼び出されるクラス 2import java.util.List; 3 4import javax.servlet.http.HttpServletRequest; 5 6import jp.co.xxx.wes.ajax.portal.MonthryReportServices; 7import jp.co.xxx.wes.com.ConnectionPool; 8import jp.co.xxx.wes.com.HtmlPage; 9import jp.co.xxx.wes.sfa.document.DocumentInfoPage; 10public class AjaxUrlMapping extends AjaxPage{ 11 12 public void mapping(){ 13 } 14 15 /** 16 * URLから実行するServicesを特定する 17 * 18 * @param request HttpServletRequest 19 * @return 20 * @throws Exception 21 */ 22 public HtmlPage set(HttpServletRequest request) throws Exception{ 23 String requestUrl = request.getRequestURI(); 24 ajaxUrl = requestUrl.split("/ajax/")[1]; 25 serviceUrl = ajaxUrl.split("/")[0]; 26 27 if(serviceUrl.equals(MonthryReportServices.SERVICES_NAME)) { 28 return new MonthryReportServices(); 29 } 30 } 31}

Java

1// Ajax Page 2package jp.co.xxx.wes.ajax; 3 4import jp.co.xxx.wes.com.HtmlPage; 5import jp.co.xxx.wes.sfa.security.MaskingWriter; 6public abstract class AjaxPage extends HtmlPage{ 7 8 /** Ajax使用時にログイン状態を判定する */ 9 public static final String PARAM_ISNOT_LOGIN_AJAX_ALLOW = "isNotLoginAjaxAllow"; 10 11 private Exception exception; 12 private HtmlPage page_; 13 14 protected String ajaxUrl; 15 protected String serviceUrl; 16 protected String methodUrl; 17 18 public void print(MaskingWriter pw) throws Exception{ 19 if(exception != null){ 20 this.printError(pw); 21 }else{ 22 if(page_ != null){ 23 page_.print(pw); 24 }else{ 25 pw.println("success"); 26 } 27 } 28 } 29 30 public abstract void mapping() throws Exception; 31 32 private void printError(MaskingWriter pw){ 33 exception.printStackTrace(); 34 StackTraceElement[] stackTraceArray = exception.getStackTrace(); 35 for(StackTraceElement stackTrace : stackTraceArray){ 36 pw.println(stackTrace); 37 } 38 } 39 40 public void createUrl(){ 41 String requestUrl = req_.getRequestURI(); 42 43 ajaxUrl = requestUrl.split("/ajax/")[1]; 44 serviceUrl = ajaxUrl.split("/")[0]; 45 methodUrl = ajaxUrl.split("/")[1]; 46 } 47 48 public void setException(Exception e){ 49 exception = e; 50 } 51 public void setPage(HtmlPage page){ 52 page_ = page; 53 } 54 55 public HtmlPage getPage(){ 56 return page_; 57 } 58 59 60}

Java

1public class MonthryReportServices extends AjaxUrlMapping { 2 3 public static final String SERVICES_NAME = "MonthryReportServices"; 4 public static final String METHOD_PRINT_MONTHRY_REPORT = "printMonthryReport"; 5 6 7 private static String portletTitle = ""; 8 private static long portletCode = 0; 9 10 private void init() { 11 portletTitle = req_.getParameter("portletTitle"); 12 portletCode = Long.parseLong(req_.getParameter("portletCode")); 13 } 14 public void mapping() { 15 try { 16 init(); 17 if(this.methodUrl.equals(METHOD_PRINT_MONTHRY_REPORT)){ 18 try { 19 this.downloadReport(); 20 } catch (Exception e) { 21 this.setPage(printError(e, AjaxErrorPage.AJAX_ERROR_CODE_FAILED_GET)); 22 } 23 } 24 } catch (Exception e) { 25 26 } 27 } 28 29 public void downloadReport() throws Exception { 30 31 // ダウンロード対象ファイルの読み込み用オブジェクト 32 FileInputStream fis = null; 33 InputStreamReader isr = null; 34 35 // ダウンロードファイルの書き出し用オブジェクト 36 ServletOutputStream os = null; 37 OutputStreamWriter osw = null; 38 try { 39 // ダウンロード対象ファイルのFileオブジェクトを生成 40 File file = new File(downloadFilePath); 41 42 if (!file.exists() || !file.isFile()) { 43 // ファイルが存在しない場合のエラー処理 44 return; 45 } 46 47 // レスポンスオブジェクトのヘッダー情報を設定 48 res.setContentType("application/octet-stream"); 49 res.setHeader("Content-Disposition", 50 "attachment; filename=\"test.xlsx\""); 51 52 // ダウンロード対象ファイルの読み込み用オブジェクトを生成 53 fis = new FileInputStream(file); 54 isr = new InputStreamReader(fis, "ISO-8859-1"); 55 56 // ダウンロードファイルの書き出し用オブジェクトを生成 57 //↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ 58 os = res.getOutputStream(); //ここで例外が発生する 59 //↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ 60 osw = new OutputStreamWriter(os, "ISO-8859-1"); 61 62 // IOストリームを用いてファイルダウンロードを行う 63 int i; 64 while ((i = isr.read()) != -1) { 65 osw.write(i); 66 } 67 } catch (FileNotFoundException e) { 68 // 例外発生時処理 69 } catch (UnsupportedEncodingException e) { 70 // 例外発生時処理 71 } catch (IOException e) { 72 // 例外発生時処理 73 } finally { 74 try { 75 // 各オブジェクトを忘れずにクローズ 76 if (osw != null) { 77 osw.close(); 78 } 79 if (os != null) { 80 os.close(); 81 } 82 if (isr != null) { 83 isr.close(); 84 } 85 if (fis != null) { 86 fis.close(); 87 } 88 } catch (IOException e) { 89 // 例外発生時処理 90 } 91 } 92 } 93}

Java

1//Servlet側で実行しているメソッド 2 private static MaskingWriter getWriter(HttpServletRequest req, 3 HttpServletResponse resp, 4 ResourceBundle res, 5 String strPage) 6 throws java.io.IOException { 7 8 MaskingWriter pw; 9 10 if (isUseHtmlCompress(req, res)) { 11 12 String strHtmlCompressEncode = ResourceManager.getHtmlCompressEncode(null); 13 14 OutputStream out = resp.getOutputStream(); 15 GZIPOutputStream gzipOut = new GZIPOutputStream(out); 16 OutputStreamWriter writer = null; 17 18 try { 19 writer = new OutputStreamWriter(gzipOut,strHtmlCompressEncode); 20 } catch (java.io.UnsupportedEncodingException e){ 21 e.printStackTrace(); 22 writer = new OutputStreamWriter(gzipOut, "SJIS"); 23 } 24 25 PrintWriter tPW = new PrintWriter(writer,false); 26 pw = new MaskingWriter(tPW); 27 resp.setHeader("Content-Encoding","gzip"); 28 29 }else{ 30 PrintWriter tPW = resp.getWriter(); 31 pw = new MaskingWriter(tPW); 32 } 33 34 // HTML をファイル出力するときには、以下の行を有効にする 35 /* 36 pw = new jp.co.xxx.wes.driver.PrintWriterWrapper(pw, strPage, 37 "htmllog.txt"); 38 */ 39 return pw; 40 } 41

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

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

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

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

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

jimbe

2019/02/22 09:20

こちらのご質問は, 過去のご質問の続きでしょうか. 情報が断片的で全体が分かりかねます. res とは(想像は付きますが)何の変数でしょうか. 出来ればこちらのご質問のみでも完結するように追記等して頂けますでしょうか.
jimbe

2019/02/22 11:50

追記ありがとうございます. MonthryReportServices にも AjaxUrlMapping にも res の出所が見えません. 申し訳ありません, AjaxPage を追ってみようと思いますので AjaxUrlMapping の import 部分も追記をお願いしても宜しいでしょうか.
bluescat

2019/02/23 08:48

申し訳ありません、 現在ソースが見られる環境ではないので、月曜日に追記させてください。
jimbe

2019/02/25 01:17 編集

関連情報を検索しているのですが, 見つけられません. こちらの一連のコードは, **一般公開していないパッケージ** をご使用でしょうか.
bluescat

2019/02/25 01:15

申し訳ありません、おっしゃる通り、非公開パッケージの一部です。 社名は伏せていただけると助かります。
jimbe

2019/02/25 01:29

でしたら, 外部のものには仕様が分かりかねます. 仕様書をご確認の上, 開発元にお問い合わせ頂くのが良いかと思います.
bluescat

2019/02/25 01:39

お手数をお掛けしまして申し訳ありません。。 内部の有識者に確認してみます。
guest

回答1

0

ベストアンサー

既に呼び出されているメソッドの結果をこのメソッドで使用すれば良いと思います.

res.getWriter 自体で 2度目以降の呼び出しをガードしているものと思います.
また, getWriter で取れたと致しましても, それを close することはクライアントとの通信を切断してしまい, 以降の通信は出来なくなると想像します.
(再度 getWriter を呼び出せば通信が復活する(ように見える様, closeはフラグ操作のみ)という実装も不可能では無いと思いますが, そのような実装は稀かと思います)

投稿2019/02/22 10:51

編集2019/02/22 11:59
jimbe

総合スコア12634

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問