アプリのダウンロード画面を作成しています。

外部からのアクセスを防ぐ為にjar,jamをWEB-INFに配置し、
クライアントがリンクを押下すると、サーブレットを呼び出し、ダウンロード処理する、というような仕組みで作業を進めています。

アプリ容量が少ない場合(50k)は成功したのですが、
多い場合(多分100k以上?)で試した場合、アプリ側からRangeヘッダ(部分的GET)が飛ばされるので、
それの対処として、「Rangeヘッダが付加されている場合は付加されたbyte数を返す」処理を追加したのですが、「このデータは取得できません」とエラーが出てしまいます。


この件、原因が分かる方、心当たりのある方、どうぞ宜しくお願いします。m(_ _)m


環境
TOMCAT5.5


※参考
取得Range=   bytes=1340-295128

jarファイルに2回アクセスが来ている事から、
予想では、一度目の通信で0-1339まで受信し、
二度目の通信で1340-295128までを望んでいる、という感じだと思います。

回答の条件
  • 1人5回まで
  • 登録:
  • 終了:2009/02/26 15:42:54
※ 有料アンケート・ポイント付き質問機能は2023年2月28日に終了しました。

ベストアンサー

id:tsukasa57 No.1

回答回数110ベストアンサー獲得回数20

ポイント100pt

たぶん、HTTPステータス・コードの200番を返しているからだと思う。206版を返すようにしてみたらどうでしょうか。

似たような問題に遭遇していたblog記事を見つけました。

http://youkand.cocolog-nifty.com/blog/2008/05/j2eeget_e813.html

id:pikab1

さっそくの解答ありがとうございます。

そのURLも参考に作成しましたので、そこは問題ないと思います。

文字数制限の問題でソースを投稿できなくて申し訳ございません。

// Jarファイルのバイト配列作成

File file = new File(sc.getRealPath("/WEB-INF/Sample.jar"));

byte[] b = new byte[(int) file.length()];

{

BufferedInputStream bis = null;

try {

bis = new BufferedInputStream(new FileInputStream(file));

bis.read(b);

} catch (IOException e) {

e.printStackTrace();

} finally {

if (bis != null) {

try {

bis.close();

} catch (IOException e) {

e.printStackTrace();

}

bis = null;

}

}

}


// レスポンスデータを生成

boolean isRange = false;

int off = 0;

int len = b.length;

String range = request.getHeader("Range");

if (range != null && range.length() != 0) {

range = range.substring(range.indexOf("=") + 1);

off = Integer.parseInt(range.substring(0, range.indexOf("-"))) + 1;

len = Integer.parseInt(range.substring(range.indexOf("-") + 1)) + 1;

isRange = true;

}

byte[] resData = new byte[len - off];



// コンテントヘッダを設定

response.setContentType("application/octet-stream");

response.setContentLength(resData.length);

if (isRange) {

response.setHeader("Content-Range", "bytes " + (off - 1) + "-" + (len - 1) + "/" + (b.length - 1));

response.setStatus(206);

}


// 送信

BufferedOutputStream bos = null;

try {

bos = new BufferedOutputStream(response.getOutputStream());

bos.write(resData);

} catch (IOException e) {

e.printStackTrace();

} finally {

if (bos != null) {

try {

bos.close();

} catch (IOException e) {

e.printStackTrace();

}

bos = null;

}

}

2009/02/25 13:40:41
  • id:pikab1
    申し訳ありません、ソースに抜けがありました。
    レスポンスデータ作成の最後の行に下記が必要です。

    System.arraycopy(b, off, resData, 0, resData.length);
  • id:tsukasa57
    うまくいきそうなコードだと思うんだけどな。とりあえず、
    http://balusc.blogspot.com/2009/02/fileservlet-supporting-resume-and.html
    で同じようなことをしているので参考にしてみてはどうでしょう。
  • id:pikab1
    教えて頂いたURLを参考にしたら解決しました!!(^.^)
    海外のサイトは調べた事がなかったので今回の件とても参考になりました。

    本当にありがとうございました。m(_ _)m
  • id:tsukasa57
    解決して良かったですね!

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

回答リクエストを送信したユーザーはいません