ダウンロードマネージャーで一時停止/再開を実装しようとしています。Webを検索していくつかの記事を読み、それに応じてコードを変更しますが、再開が正しく機能していないようです。
if (!downloadPath.exists())
downloadPath.mkdirs();
if (outputFileCache.exists())
{
downloadedSize = outputFileCache.length();
connection.setAllowUserInteraction(true);
connection.setRequestProperty("Range", "bytes=" + downloadedSize + "-");
connection.setConnectTimeout(14000);
connection.connect();
input = new BufferedInputStream(connection.getInputStream());
output = new FileOutputStream(outputFileCache, true);
input.skip(downloadedSize); //Skip downloaded size
}
else
{
connection.setConnectTimeout(14000);
connection.connect();
input = new BufferedInputStream(url.openStream());
output = new FileOutputStream(outputFileCache);
}
fileLength = connection.getContentLength();
byte data[] = new byte[1024];
int count = 0;
int __progress = 0;
long total = downloadedSize;
while ((count = input.read(data)) != -1 && !this.isInterrupted())
{
total += count;
output.write(data, 0, count);
__progress = (int) (total * 100 / fileLength);
}
output.flush();
output.close();
input.close();
さて、問題は修正されました。ここに、一時停止/再開を実装したい他のユーザーのための私のコードがあります:
if (outputFileCache.exists())
{
connection.setAllowUserInteraction(true);
connection.setRequestProperty("Range", "bytes=" + outputFileCache.length() + "-");
}
connection.setConnectTimeout(14000);
connection.setReadTimeout(20000);
connection.connect();
if (connection.getResponseCode() / 100 != 2)
throw new Exception("Invalid response code!");
else
{
String connectionField = connection.getHeaderField("content-range");
if (connectionField != null)
{
String[] connectionRanges = connectionField.substring("bytes=".length()).split("-");
downloadedSize = Long.valueOf(connectionRanges[0]);
}
if (connectionField == null && outputFileCache.exists())
outputFileCache.delete();
fileLength = connection.getContentLength() + downloadedSize;
input = new BufferedInputStream(connection.getInputStream());
output = new RandomAccessFile(outputFileCache, "rw");
output.seek(downloadedSize);
byte data[] = new byte[1024];
int count = 0;
int __progress = 0;
while ((count = input.read(data, 0, 1024)) != -1
&& __progress != 100)
{
downloadedSize += count;
output.write(data, 0, count);
__progress = (int) ((downloadedSize * 100) / fileLength);
}
output.close();
input.close();
}
さらに情報がなければ何が悪いのかを知ることは不可能ですが、次のことに注意してください:
Originが実際にRangeリクエストを実際にサポートしていることをテストする簡単なもの(curlやwgetなど)で範囲リクエストを確認する必要があります。
サーバーが応答するのに時間がかかる(タイムアウト制限を超える)こと、またはすべてのサーバーが一時停止-再開をサポートしているわけではないことも事実です。また、ファイルがHttp、https、ftp、またはudp経由でダウンロードされることを熟考することも重要です。
一時停止」とは、ストリームの一部を読み取ってディスクに書き込むことを意味します。再開する場合は、ヘッダーを使用してダウンロードするものを指定する必要があります 。
あなたは次のようなことを試すかもしれません:
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
if(ISSUE_DOWNLOAD_STATUS.intValue()==ECMConstant.ECM_DOWNLOADING){
File file=new File(DESTINATION_PATH);
if(file.exists()){
downloaded = (int) file.length();
connection.setRequestProperty("Range", "bytes="+(file.length())+"-");
}
}else{
connection.setRequestProperty("Range", "bytes=" + downloaded + "-");
}
connection.setDoInput(true);
connection.setDoOutput(true);
progressBar.setMax(connection.getContentLength());
in = new BufferedInputStream(connection.getInputStream());
fos=(downloaded==0)? new FileOutputStream(DESTINATION_PATH): new FileOutputStream(DESTINATION_PATH,true);
bout = new BufferedOutputStream(fos, 1024);
byte[] data = new byte[1024];
int x = 0;
while ((x = in.read(data, 0, 1024)) >= 0) {
bout.write(data, 0, x);
downloaded += x;
progressBar.setProgress(downloaded);
}
そして物事を同期してみてください。
この行からデバッグを開始します。
connection.setRequestProperty("Range", "bytes=" + downloadedSize + "-");
ソースコードからはdownloadedSize
が何であるかを判別できないため、さらに詳しく説明することは困難ですが、形式はbytes=from-to
。
とにかく、よくある落とし穴を避けるために Apache HttpClient を使用することをお勧めします。 ここ は、同様のトピックでApache HttpClientを使用する人からの質問であり、いくつかのサンプルコードが提供されています。
Input.skip(downloadedSize)行を削除する必要があるだけだと思います。バイト範囲のHTTPヘッダーを設定すると、サーバーは送信これらのバイトをスキップします。
「aaaaabbbbbcccccddddd」で構成される20バイトの長さのファイルがあり、5バイトのダウンロード後に転送が一時停止したとします。次に、Rangeヘッダーにより、サーバーは "bbbbbcccccddddd"を送信します。このコンテンツのallを読み取り、ファイルに追加する必要があります-skip()はありません。ただし、コード内のskip()呼び出しは、「bbbbb」をスキップして、「cccccddddd」をダウンロードします。ファイルの少なくとも50%を既にダウンロードしている場合、skip()はすべての入力を使い果たし、何も起こりません。
また、stringy05の投稿のすべてが適用されます。サーバーでHTTP/1.1がサポートされていること、リソースでRangeヘッダーがサポートされていること(動的に生成されたコンテンツではサポートされていない可能性があること)、etagと変更日を使用してリソースが変更されていないことを確認してください。