【发布时间】:2014-05-17 06:52:43
【问题描述】:
尊敬的前辈您好:)
我的目标: 在给定一个 URL 的情况下,通过在 Java 中使用多线程下载一个 URL 资源,即将一个文件下载到多个部分(很像 IDM 的做法)并在末尾下载,将它们全部合并为 1 个最终文件。
使用的技术: Java、RandomAccessFile、多线程、InputStreams
问题: 该文件以精确的 KB 大小下载,我检查了很多次,但最终文件已损坏。例如,如果我下载一个图像,它会有些模糊,如果我下载一个 .exe,它下载正常,但是当我运行 .exe 文件时,它说“媒体已损坏,请重试下载”。
这是我的主代码,我从中调用线程类,其中包含文件名、连接的起始范围和结束范围等参数,以及每个线程的 JProgressBar,它们将分别更新自己的.
public void InitiateDownload()
{
HttpURLConnection uc = (HttpURLConnection) url.openConnection();
uc.connect();
long fileSize = uc.getContentLengthLong();
System.out.println("File Size = "+ fileSize );
uc.disconnect();
chunkSize = (long) Math.ceil(fileSize/6);
startFrom = 0;
endRange = (startFrom + chunkSize) - 1;
Thread t1 = new MyThread(url, fileName, startFrom, endRange, progressBar_1);
t1.start();
//-----------------------------------------
startFrom += chunkSize;
endRange = endRange + chunkSize;
System.out.println("Part 2 :: Start = " + startFrom + "\tEnd To = " + endRange );
Thread t2 = new MyThread(url, fileName, startFrom, endRange, progressBar_2);
t2.start();
//-----------------------------------------
//..
//..
//..
//-----------------------------------------
startFrom += chunkSize;
long temp = endRange + chunkSize;
endRange = temp + (fileSize - temp); //add any remaining bits, that were rounded off in division
Thread t6 = new MyThread(url, fileName, startFrom, endRange, progressBar_6);
t6.start();
//-----------------------------------------
}
这是 MyThread 类的 run() 函数:
public void run() {
Thread.currentThread().setPriority(MAX_PRIORITY);
System.setProperty("http.proxyHost", "192.168.10.50");
System.setProperty("http.proxyPort", "8080");
HttpURLConnection uc = null;
try {
uc = (HttpURLConnection) url.openConnection();
uc.setRequestProperty("Range", "bytes="+startFrom+"-"+range);
uc.connect();
fileSize = uc.getContentLengthLong();
inStream = uc.getInputStream();
int[] buffer = new int[ (int) totalDownloadSize ];
file.seek(startFrom); //adjusted start of file
这就是我认为问题所在,
run() 继续...
for(int i = 0 ; i < totalDownloadSize; i++)
{
buffer[i] = inStream.read();
file.write(buffer[i]);
//Updating Progress bars
totalDownloaded = totalDownloaded + 1;
int downloaded = (int) (100 * ( totalDownloaded/ (float) totalDownloadSize)) ;
progressbar.setValue( downloaded );
}
System.err.println( Thread.currentThread().getName() + "'s download is Finished!");
uc.disconnect();
}
catch(IOException e) {
System.err.println("Exception in " + Thread.currentThread().getName() + "\t Exception = " + e );
}
finally {
try {
file.close();
if(inStream!=null)
inStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
现在文件以完整大小下载,但正如我所说,它的一小部分已损坏。
现在,
如果我用下面的while 循环替换for loop,问题就完全解决了。
int bytesRead = 0;
byte[] buffer = new byte[ (int) totalDownloadSize ];
file.seek(startFrom); //adjusted start of file
while( (bytesRead = inStream.read(buffer) ) != -1 ) {
file.write(buffer, 0, bytesRead);
}
但我需要 for 循环来测量每个线程已下载了多少文件,并且我想升级线程的相应 JPROGRESSBAR。
请帮我解决 for 循环逻辑。
或
如果您能建议我如何在while 循环中升级 Jprogressbars。我似乎无法找到一种方法来量化线程下载了多少文件...
我已经花了很多时间,现在我非常疲倦......
【问题讨论】:
标签: java multithreading file-io inputstream httpurlconnection