• ベストアンサー
  • すぐに回答を!

Strutsによるバイナリファイル出力

FileInputStream stream =new FileInputStream("C:/Test.exe"); String filename = "Test1.exe"; int bytesRead = 0; byte[] buffer = new byte[256]; HttpResponse.setContentType("application/octet-stream; charset=UTF-8"); HttpResponse.setHeader("Content-Disposition","attachment; filename=\""+filename+"\""); ServletOutputStream sos =HttpResponse.getOutputStream(); while ((bytesRead = stream.read(buffer,0,256) != -1) {  sos.write(buffer); } sos.flush(); sos.close(); stream.close(); 以上のコードでローカル内にあるファイルを名前を変え転送していますが クライアントにより正常なファイルだったり異常なファイルだったりします。 異常なファイルはクライアントによりばらばらですが、ファイルサイズが正常のものより少し大きかったりします。 バッファーではなくバイト単位での転送も試みたのですが 結果は同じでした。 何かおかしい点ありましたらご指摘いただけますでしょうか。

共感・応援の気持ちを伝えよう!

  • 回答数1
  • 閲覧数708
  • ありがとう数1

質問者が選んだベストアンサー

  • ベストアンサー
  • 回答No.1
  • ukiuni
  • ベストアンサー率100% (2/2)

OutputStreamの使い方の問題ですね。 で、OutPutStream#write(byte[] buffer)は、bufferのすべてを書き込む、と言うものです。 記載のコードの問題はInputStreamで読み込んでいない分のbufferまで書き込まれてしまうものです。 例えば、「ABCDEFGH」と言うファイルがあり、bufferが3文字読み込めるとして ABC DEF GH のようにbufferには読み込まれますが、bufferは三文字分なので、「GH」を読み込んだ際に、前回読み込んでいたFが上書きされずに残ります。書き込んだときは ABC DEF GHF となります。 正しいコードは sos.write(buffer);⇒sos.write(buffer,0,bytesRead); と、読み込んだ分だけ、出力するようにします。

共感・感謝の気持ちを伝えよう!

質問者からのお礼

ukiuni様 ご回答ありがとうございました。 非常に丁寧で分かりやすいご解説感謝いたします。 ukiuni様が書かれた様に修正を行ったのですが やはりクライアントにより、できたりできなかったりします。 ですが、以前のように同クライアントでできたりできなかったりという現象はなくなりました。 こうなるとクライアントの環境次第のような気もするのですが ありえないという気もします… なにか他に気付かれた点ございませんでしょうか

関連するQ&A

  • ファイルのダウンロードが遅い

    windows環境のクライアントPCにブラウザからファイルをダウンロードさせる javaプログラムを作成しています。 linuxのサーバー側でcsvを圧縮したzipファイルを作成しているのですが zipの作成処理までは速いのに、その後のファイル保存のダイアログに とても時間がかかります。なぜなのか分からず困っています。 以下、保存ダイアログ表示のコードです。 --------------------------------------------- FileInputStream fi = new FileInputStream(ファイルパス/temp.zip); byte[] b = new byte[fi.available()]; for (int i = 0; i < b.length; i++) b[i] = (byte)fi.read(); response.setContentType("application/octet-stream; charset=Windows-31J"); response.setHeader("Content-Disposition","attachment; filename=\"temp.zip\""); response.setContentLength(b.length); ServletOutputStream os = response.getOutputStream(); os.write(b); os.close(); fi.close(); --------------------------------------------- ご教授お願いします。

    • ベストアンサー
    • Java
  • strutsでファイルダウンロード(WinでOK,linuxでNG)

    strutsでWindowsのexeファイルのダウンロードを実装しましたが、Windows上のtomcatにdeployすると正常にダウンロードできるのに、linux(fedora-core3)上のtomcatにdeployすると、ダウンロードしたファイルがhtmlになってしまいます。 hoge.exeという名前のファイルはダウンロードできるのですが、それが実はテキストで、メモ帳で開くと、ダウンロード画面のhtmlが表示されます。 この状況は何によって生み出されているのでしょうか。 お分かりになる方、ヒントをお願いいたします。 以下にファイルダウンロード部のソース(抜粋)を掲載させていただきます。 ----- 以下ソース ----- protected void download(HttpServletResponse response, String fileType, String filename) { try { // exeファイルのダウンロード時 if (fileType.equals("application/octet-stream")) { response.setHeader("Content-Disposition", "attachment; filename=" + filename); } response.setContentType(fileType); BufferedInputStream bis = new BufferedInputStream(new FileInputStream(filename)); BufferedOutputStream bos = new BufferedOutputStream(response.getOutputStream()); byte[] buf = new byte[128]; int size; while ((size = bis.read(buf, 0, buf.length)) != -1) { bos.write(buf, 0, size); } bos.close(); bis.close(); } catch (IOException e) { throw new thisSystemException("could not send file[" + filename + "]"); }

    • ベストアンサー
    • Java
  • ファイル転送が正常に動作しない

    サーバ側からクライアント側へファイル転送をJavaで行おうとしています。 そこで以下のようなプログラムを作成し、実行するのですが 実行自体はうまくいき、1つめのファイルはきちんと転送できるのですが、 2つめのファイルが転送完了後に確認すると0バイトとなっており、 きちんと動作しません。どうするべきでしょうか。 サーバ側 ※上でソケットはつないであります。 if(command.equals("put.") == true){ System.out.println("putモードに入りました"); // カーネル(linux.uml)の送信 String filename1 = args[1]; byte[] data1 = new byte[1024]; //ストリームの作成 FileInputStream fin1= new FileInputStream(filename1); BufferedOutputStream out2 = new BufferedOutputStream(sock.getOutputStream()); System.out.println("送信ファイル : " + filename1); //int totalSize1 = 0; int len1; while((len1 = fin1.read(data1)) != -1){ out2.write(data1); } out.flush(); fin1.close(); System.out.println(filename1 + "を送信完了しました"); // ルートファイルシステム(uml-root-hardy)の送信 String filename2 = args[2]; byte[] data2 = new byte[1024]; //ストリームの作成 FileInputStream fin2 = new FileInputStream(filename2); //ファイルの内容を読み出し、送信する System.out.println("送信ファイル" + filename2); //long totalSize2 = 0; long len2 = 0; while((len2 = fin2.read(data2)) != -1){ out2.write(data2); } out.flush(); fin2.close(); System.out.println(filename2 + "を送信完了しました"); } クライアント側 ※上でソケットはつないであります。 if(change.equals("put.") == true){ System.out.println("putモードに入りました"); // 2つのファイルを転送する // カーネル(linux.uml)の転送 String filename1 = args[2]; System.out.println("受信するファイル : " + filename1); // FileOutputStreamの作成 FileOutputStream fout1 = new FileOutputStream(filename1); BufferedInputStream in2 = new BufferedInputStream(sock.getInputStream()); int recvMsgSize1; int bufSize = 1024; byte[] byteBuffer1 = new byte[bufSize]; //int totalByte1 = 0; while((recvMsgSize1 = in2.read(byteBuffer1)) != -1){ fout1.write(byteBuffer1); } System.out.println(filename1 + "を受信完了しました"); fout1.close(); // ルートファイルシステム(uml-root-hardy)の転送 String filename2 = args[3]; System.out.println("受信するファイル : " + filename2); FileOutputStream fout2 = new FileOutputStream(filename2); long recvMsgSize2; //byte[] byteBuffer = new byte[bufSize]; byte[] byteBuffer2 = new byte[bufSize]; //long totalByte2 = 0; while((recvMsgSize2 = in2.read(byteBuffer2)) != -1){ fout2.write(byteBuffer2); } System.out.println(filename2 + "を受信完了しました"); fout2.close(); } またプログラム中では、サーバ、クライアントでそれぞれ len1,len2(サーバ側)、recvMsgSize1,recvMsgSize2(クライアント側) に警告で「ローカル変数len1(recvMsgSize1)は読み取られません」 と出ています。 どのように解決するべきでしょうか。

    • ベストアンサー
    • Java
  • バイナリファイルの出力

    「test.dat」というファイルをブラウザから ダウロードさせるためにバイナリ出力をしたいのですが、 空ファイルばかりできて上手くいきません。 以下のようなコードなのですが、どこが悪いでしょうか? ご教授ください。お願いします。 症状:ブラウザからダウンロードすると、ファイル名は正しいが 空のファイルになっている 環境:perl 5.8.7 windows server2003 ----------------------------------------------------------- #!/usr/local/bin/perl print "Content-Disposition: attachment; filename=\"test.dat\"\n"; print "Content-Type: application/octet-stream\n\n"; open(IN, "test.dat"); binmode(IN); binmode(STDOUT); print while (<IN>); close(IN); -----------------------------------------------------------

    • ベストアンサー
    • Perl
  • バイナリファイルを転送したいのですが

    お世話になります socketを用いてサーバへファイルを転送したいのですが、うまくいきません。 以下ソースからの抜粋です BufferedOutputStream out = new BufferedOutputStream(socket.getOutputStream()); BufferedInputStream in = new BufferedInputStream(new FileInputStream("test.txt")); int c; while((c = in.read()) != -1 ){  out.write(c); } 上記のようなコーディングでは転送できないのでしょうか? 出来ればファイルから1024バイトずつ読み込んで1024バイトずつ出力していき、ファイルの終端まで繰り返す処理をしたいのですが、よい方法をご存知でしたら教えていただけないでしょうか?

    • ベストアンサー
    • Java
  • バイナリファイルの読み込み方

    バイナリファイルの中身を解析したいと思っています。 「先頭の3バイトは日付、次の2バイトはファイルサイズ、 さらに次の4バイトはファイル種類が格納」というようにファイルのフォーマット が定まっている場合、どのように読み込めばよいでしょうか。 下記のコードを改変してできないかと思っています。 import java.io.BufferedInputStream; import java.io.FileInputStream; import java.io.IOException; public class BinaryRead { public static void main(String[] args) { BufferedInputStream bi = null; int tmp=0; try { //インスタンス生成 bi = new BufferedInputStream(new FileInputStream("hoge.dat")); //ストリームの終わりに達した場合は-1 while((tmp=bi.read())!=-1){ System.out.println(tmp); } } catch (Exception e){ e.printStackTrace(); } finally { //入力ストリームを閉じる bi.close(); } } }

    • ベストアンサー
    • Java
  • socketでのバイナリファイルの扱い方

    javaのsocketを用いてファイルの送信サーバ、受信クライアントを作成しているのですが テストプログラムとしてスレッド化せずに送信・受信部のみ作りました。 症状はバイナリデータの転送がうまくできないことです。ソースを抜粋すると サーバ側で BufferedOutputStream out = new BufferedOutputStream(socket.getOutputStream());//socketはSocketクラス BufferedInputStream in1 = new BufferedInputStream( new FileInputStream("test1.bmp")); BufferedInputStream in2 = new BufferedInputStream( new FileInputStream("test2.bmp")); while( (c = in1.read() ) != -1 ){   out.write(c); } while( (c = in2.read() ) != -1 ){   out.write(c); } クライアント側で BufferedOutputStream out1 = new BufferedOutputStream( new FileOutputStream("test1.out.bmp") ); BufferedOutputStream out2 = new BufferedOutputStream( new FileOutputStream("test2.out.bmp") ); BufferedInputStream in = new BufferedInputStream( s.getInputStream() ); while( ( c=in.read() ) != -1 ){   out1.write(c); } while( ( c=in.read() ) != -1 ){   out2.write(c); } とやっています。 クライアント側で1回目のin.readを抜けるときにはサーバ側は既に2回のwriteを終わっているようで ファイルはtest1.out.bmpにマージされていました。 サーバ側の1回目のwriteのオブジェクトがcloseしていないことが原因だと思い1回目のwriteが終わった時点でout.close()とした のですがそうやるとsocketも閉じてしまいsocket closeのエラーが生じてしまいました。 このようにならず1本のコネクションでバイナリのデータを複数送信する方法をご存知でしたら教えてください。 [環境] win2ksp1a,j2sdk1.4.1_03,java経験4ヶ月程度

  • バイナリの読み込みから出力まで

    こんばんは、バイナリの扱いについて質問させてください。 やりたいことはこんな感じです。 (1) hoge.mp3ファイルをバイナリで読み込む。 (2) バイナリの1000バイト目から200バイトの範囲を抜き出す。 (3) 抜き出したバイナリをファイルshort.mp3として保存する。 下の構文だとそもそもコンパイルすら通らないのですが、 やりたいことを少しでも伝えたいので、あえて書かせていただきました。 どうかよろしくお願い致します。 FileInputStream fis = new FileInputStream("hoge.mp3"); // hoge.mp3の1000バイト目から200バイト分抜き出す。 byte[] pick = fis.read(fis, 1000, 200); DataOutputStream dout = new DataOutputStream(new FileOutputStream("short.mp3")); dout.write(pick);

    • ベストアンサー
    • Java
  • バイナリファイルでOutOfMemoryエラー

    お世話になります。 ブラウザ画面からファイルをアップロードし、そのバイナリデータを返すメソッドを作成したのですが、約50MB以上のファイルを使用するとOutOfMemoryエラーとなりJava heap spaceが足りないといわれてしまいます。ヒープサイズをあげればエラーはしなくなるとはおもいますが、根本的な解決にはならないと思います。 public byte[] upload(FormFile ff) throws Exception { ByteArrayOutputStream baos = new ByteArrayOutputStream(); InputStream is = ff.getInputStream(); BufferedInputStream bis = new BufferedInputStream(is); byte[] byteData; try { int data = 0; byte[] buffer = new byte[1024]; while ((data = bis.read(buffer) != -1) { baos.write(buffer, 0, data); } byteData = baos.toByteArray(); } catch (IOException e) { throw e; } finally { if (null != bis) { bis.close(); } } return byteData; } 以上のようなメソッドなのですが、おかしい点はありますでしょうか。 指摘していただけると助かります。 よろしくお願いいたします。

    • ベストアンサー
    • Java
  • java utf-8 で ファイル出力

    【やりたい事】  ファイルを読み込んで、改行コードCRLFをLFに変換して、空白行は削除して、「正常終了しました。」は削除。  文字コードUTF8で出力したい。 【問題】  UTF-8で指定してるのに、Shift_JISで出力される。 【入力ファイル】  ファイル名:test.tsv  文字コード:UTF-8  改行コード:CRLF ************************ test test1 1 2 1 3 正常終了しました。 ************************ 【現在のソース】 import java.io.*; public class writeFile { /** * @param args */ public static void main(String[] args) { // TODO 自動生成されたメソッド・スタブ try { //(1)FileReaderオブジェクトinFileを生成 FileReader inFile = new FileReader("test.tsv"); //(2)FileWriterオブジェクトoutFileを生成 FileWriter outFile = new FileWriter("test_lf.tsv"); //(3)BufferedReaderオブジェクトinBufferを生成 BufferedReader inBuffer = new BufferedReader(inFile); //(4)BufferedWriterオブジェクトoutBufferを生成 BufferedWriter outBuffer = new BufferedWriter(outFile); String line; int cnt=0; //(5)読み込みデータがなくなるまで、読み込み while ((line = inBuffer.readLine()) != null) { //(6)データの書き込み処理 if (line.equals("")){ cnt=cnt+1; }else{ if(cnt<=1){ outBuffer.write(line+"\n"); } } } outBuffer.flush(); //(7)バッファをフラッシュ inBuffer.close(); //(8)読み込みストリームのクローズ outBuffer.close(); //(9)書き込みストリームのクローズ } catch (IOException e) { } try { //(1) //(2)FileInputStreamオブジェクトの生成 FileInputStream abc = new FileInputStream("test_lf.tsv"); //(3)FileOutputStreamオブジェクトの生成 FileOutputStream xyz = new FileOutputStream("test_lf_utf.tsv"); //(4)InputStreamReaderオブジェクトの生成 InputStreamReader in = new InputStreamReader(abc, "Shift_JIS"); //(5)OutputStreamWriterオブジェクトの生成 OutputStreamWriter out = new OutputStreamWriter(xyz, "UTF-8"); int contents; //(6) //(7)読み込むデータがなくなるまで読み込み while ((contents = in.read()) != -1) { //(8)書き込むデータがなくなるまで書き込み out.write(contents); } in.close(); //(9)読み込みストリームを閉じる out.close(); //(10)書き込みストリームを閉じる } catch(IOException e) { } } } 【出力結果】  ファイル名:test_lf.tsv  文字コード:Shift_JIS  改行コード:LF ************************  test test1 1 2 1 3 ************************  ファイル名:test_lf_utf.tsv  文字コード:Shift_JIS  改行コード:LF ************************ test test1 1 2 1 3 ************************ 本当に困っています。 もう二日、はまってます。 ご教授願います。

    • ベストアンサー
    • Java