package multiThreadDownload;
import java.io.*;
import java.net.*;
import org.apache.commons.httpclient.*;
import org.apache.commons.httpclient.methods.*;
import org.apache.commons.logging.*;
public class HttpTask extends Task {
private static final HttpClient httpClient;
private static final Log logger = LogFactory.getLog(HttpTask.class);
static {
MultiThreadedHttpConnectionManager connectionManager =
new MultiThreadedHttpConnectionManager();
connectionManager.getParams().setDefaultMaxConnectionsPerHost(20);
httpClient = new HttpClient(connectionManager);
}
private URL url;
private File destination;
private int threadCounts;
private long contentLength;
private volatile boolean stop = false;
private int workerCompleted = 0;
private HttpTaskWorker[] workers;
private RandomAccessFile store;
private DownloadListener listener;
public HttpTask(String url, String dest, int threadCounts)
{
if (url == null || dest == null) {
throw new NullPointerException();
}
if (threadCounts <= 0) {
throw new IllegalArgumentException();
}
try {
this.url = new URL(url);
if (!this.url.getProtocol().equals("http")) {
throw new IllegalArgumentException("Unsupported URL Scheme");
}
this.destination = new File(dest);
if (!(destination.exists() && destination.isDirectory()
&& destination.canWrite())) {
throw new IllegalArgumentException("Illegal destination folder");
}
this.threadCounts = threadCounts;
workers = new HttpTaskWorker[threadCounts];
}
catch (MalformedURLException ex) {
throw new IllegalArgumentException("Illegal Resource URL");
}
}
protected long getResourceContentLen() throws HttpException, IOException
{
HeadMethod head = new HeadMethod(url.toString());
head.setFollowRedirects(false);
int statusCode = httpClient.executeMethod(head);
if (statusCode == HttpStatus.SC_MOVED_TEMPORARILY){
String recentUrl = head.getResponseHeader("Location").getValue();
logger.info("URL redirection: " + recentUrl);
this.url = new URL(url.getProtocol(),
url.getHost(),
url.getPort(),
recentUrl);
head = new HeadMethod(url.toString());
statusCode = httpClient.executeMethod(head);
}
if (statusCode == HttpStatus.SC_OK) {
destination = new File(destination,
new File(url.getPath()).getName());
store = new RandomAccessFile(destination, "rw");
logger.info("File " + destination.getName() + " Created.");
listener.onProgress("File " + destination.getName() + " Created.");
return head.getResponseContentLength();
}
else {
throw new UnsupportedOperationException();
}
}
public void start() {
String msg = "Starting to download URL: " + url.toString();
logger.info(msg);
listener.onProgress(msg);
try {
contentLength = getResourceContentLen();
msg = "Resource Content Length is " + contentLength;
logger.info(msg);
listener.onProgress(msg);
listener.onGetContentLength(destination.getName(), contentLength);
long chunk = contentLength / threadCounts;
long startPos = 0;
long endPos;
for (int i = 0; i < threadCounts; i++)
{
endPos = startPos + chunk;
if (i == threadCounts - 1) {
endPos = contentLength;
}
workers[i] = new HttpTaskWorker(
"Worker Thread #" + (i + 1),
startPos, endPos - 1);
workers[i].start();
startPos = endPos;
}
}
catch(Exception ex) {
logger.fatal(ex);
ex.printStackTrace();
}
}
public void stop() {
stop = true;
}
public void resume(){
stop = false;
for (int i = 0; i < workers.length; i++) {
if (!workers[i].isDone()) {
workers[i] = new HttpTaskWorker(
"Worker Thread #" + (i+1),
workers[i].startPos,
workers[i].endPos, workers[i].complete);
workers[i].start();
}
}
}
public synchronized void onWorkerComplete() {
workerCompleted++;
if (workerCompleted == threadCounts) {
String msg = "!!!!!!Download Completed.!!!!!!";
logger.info(msg);
listener.onProgress(msg);
try {
store.close();
}
catch(IOException ioe) {
logger.error(ioe);
}
}
}
protected synchronized void saveChunk(byte[] buf, int offset, int len, long absPos)
throws IOException {
store.seek(absPos);
store.write(buf, offset, len);
}
public void addDownloadListener(DownloadListener listener) {
this.listener = listener;
}
/**
* Http Resource download worker thread.
*/
protected class HttpTaskWorker extends Thread {
/**
* bytes range start position.
*/
private long startPos;
/**
* bytes range end position.
*/
private long endPos;
/**
* bytes number completed.
*/
private long complete;
/**
* create Http resource download worker thread with specified bytes range
* and already completed bytes.
* @param name worker thread name
* @param startPos bytes range start position.
* @param endPos bytes range end position.
* @param complete bytes number completed.
*/
public HttpTaskWorker(String name, long startPos, long endPos, long complete) {
super(name);
this.startPos = startPos;
this.endPos = endPos;
this.complete = complete;
String msg = getName() + " Worker Created: startPos = "
+ startPos
+ " endPos = "
+ endPos
+ " Complete = "
+ complete;
logger.info(msg);
listener.onProgress(msg);
}
/**
* create Http resource download worker thread with specified bytes range
*
* @param name
* @param startPos
* @param endPos
*/
public HttpTaskWorker(String name, long startPos, long endPos) {
this(name, startPos, endPos, 0);
}
private boolean isDone() {
return endPos - startPos == complete;
}
public void run() {
GetMethod get = createGetMethod();
try {
InputStream in;
byte buf[] = new byte[4096];
int bytesRead;
int bytesNeedToSave;
int chunkSize = (int)(endPos - startPos + 1);
while (!stop && complete < chunkSize) {
httpClient.executeMethod(get);
in = get.getResponseBodyAsStream();
while ((bytesRead = in.read(buf)) != -1 && complete < chunkSize) {
String msg = getName() + "Bytes read " + bytesRead + " bytes";
logger.debug(msg);
//listener.onProgress(msg);
bytesNeedToSave = (int)(bytesRead + complete > chunkSize ? chunkSize - complete : bytesRead);
if (bytesNeedToSave > 0)
listener.onReadChunk(this.getName(), bytesNeedToSave);
saveChunk(buf, 0, bytesNeedToSave, startPos + complete);
complete += bytesNeedToSave;
}
String msg = getName() + " Bytes Completed: " + complete + " bytes";
logger.info(msg);
listener.onProgress(msg);
}
}
catch(HttpException he) {
logger.error(he);
}
catch(IOException ioe) {
logger.error(ioe);
listener.onProgress(getName() + " " + ioe.getMessage());
}
finally {
get.releaseConnection();
String msg = getName() + " " + "Http Connection released.";
logger.info(msg);
listener.onProgress(msg);
}
String msg= getName() + " Download complete. :)";
logger.info(msg);
listener.onProgress(msg);
onWorkerComplete();
}
protected GetMethod createGetMethod() {
GetMethod get = new GetMethod(url.toString());
get.addRequestHeader("Accept", "*/*");
get.addRequestHeader("User-Agent",
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.1.4322)");
get.addRequestHeader("Pragma", "no-cache");
get.addRequestHeader("Cache-Control","no-cache");
get.addRequestHeader("Connection", "close");
if (startPos + complete > 0) {
String bytesRange = String.valueOf(startPos + comple
没有合适的资源?快使用搜索试试~ 我知道了~
温馨提示
【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、python、web、C#、EDA、proteus、RTOS等项目的源码。【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。
资源推荐
资源详情
资源评论
收起资源包目录
基于java的多线程与线程安全实践-基于java的Http协议的断点续传.rar (73个子文件)
Java多线程与线程安全实践-基于Http协议的断点续传
MultiThreadDownload
multiThreadDownload
ConsoleDownloader.class 2KB
DownloadEvent.class 304B
HttpTask.class 7KB
ConsoleDownloader.java 1KB
NewTaskDialog.java 4KB
GUIDownloadListener$2.class 1KB
HttpTask.java 8KB
BatchTaskAction.class 2KB
NewTaskDialog.class 5KB
DownloadAdapter.java 362B
DownloadListener.java 831B
NewTaskAction.class 2KB
ConsoleDownloadListener.java 416B
BatchTaskDialog.java 5KB
GUIDownloader.java 5KB
ExitAction.class 604B
ExitAction.java 477B
BatchTaskAction.java 896B
GUIDownloader$1.class 1KB
ConsoleDownloadListener.class 970B
NewAboutDialog.class 2KB
DeleteTaskAction.java 435B
GUIDownloader$2.class 727B
DownloadException.java 89B
AboutAction.java 465B
DownloadException.class 319B
BatchTaskDialog$1.class 2KB
icons
checked.gif 892B
unchecked.gif 877B
disabledCount.gif 860B
disabledSaveAs.gif 883B
Thumbs.db 24KB
count.gif 860B
rightArrow.gif 999B
save.gif 891B
disabledSave.gif 871B
new.gif 874B
disabledAbout.gif 950B
disabledAddBook.gif 893B
about.gif 968B
saveAs.gif 893B
addBook.gif 893B
disabledNew.gif 862B
open.gif 877B
disabledRemoveBook.gif 911B
disabledOpen.gif 861B
removeBook.gif 911B
NewTaskAction.java 776B
DeleteTaskAction.class 1KB
BatchTaskDialog.class 6KB
NewTaskDialog$1.class 2KB
GUIDownloadListener$3.class 1KB
HttpTask$HttpTaskWorker.class 5KB
Task.class 325B
DownloadEvent.java 197B
DownloadListener.class 354B
GUIDownloader.class 7KB
DownloadAdapter.class 946B
AboutAction.class 1KB
GUIDownloadListener.class 5KB
Task.java 167B
GUIDownloader$3.class 847B
NewAboutDialog.java 2KB
GUIDownloadListener.java 4KB
GUIDownloadListener$1.class 1KB
lib
commons-httpclient-3.0.1.jar 273KB
commons-logging-adapters-1.1.jar 20KB
commons-logging-1.1.jar 52KB
commons-logging-api-1.1.jar 44KB
commons-codec-1.3.jar 46KB
.classpath 2KB
.project 395B
swt-win32-3138.dll 308KB
共 73 条
- 1
资源评论
CrMylive.
- 粉丝: 1w+
- 资源: 4万+
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功