package org.arong.egdownloader.ui.work;
import java.io.File;
import java.io.InputStream;
import java.net.SocketTimeoutException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.SwingWorker;
import org.apache.commons.httpclient.ConnectTimeoutException;
import org.arong.egdownloader.model.Picture;
import org.arong.egdownloader.model.ScriptParser;
import org.arong.egdownloader.model.Setting;
import org.arong.egdownloader.model.Task;
import org.arong.egdownloader.model.TaskStatus;
import org.arong.egdownloader.spider.WebClient;
import org.arong.egdownloader.ui.ComponentConst;
import org.arong.egdownloader.ui.table.TaskingTable;
import org.arong.egdownloader.ui.window.EgDownloaderWindow;
import org.arong.util.FileUtil;
import org.arong.util.Tracker;
/**
* 下载线程类,执行耗时的下载任务
* @author 阿荣
* @since 2014-05-25
*/
public class DownloadWorker2 extends SwingWorker<Void, Void>{
private JFrame mainWindow;
private Task task;
private Setting setting;
TaskingTable table;
private int exceptionNum = 0;
private int success = 0;//下载完成个数
private int requireNum = 0;//需要下载数(未下载数)
private int maxthread = 5;
private int running = 0;
public DownloadWorker2(Task task, JFrame mainWindow){
this.mainWindow = mainWindow;
this.task = task;
setting = ((EgDownloaderWindow)mainWindow).setting;
table = (TaskingTable) ((EgDownloaderWindow)mainWindow).runningTable;
}
protected Void doInBackground() throws Exception {
//设置任务状态为下载中
task.setStatus(TaskStatus.STARTED);
Tracker.println(getClass(), task.getName() + "(" + task.getStart() + "-" + task.getEnd() + "):开始下载");
List<Picture> pics = task.getPictures();
if(pics.size() != 0){
for(int i = (task.getStart() < 1 ? 0 : task.getStart() - 1); i < task.getEnd() && i < pics.size(); i ++){
Picture pic = pics.get(i);
if(pic.getUrl() != null && ! pic.isRunning() && !pic.isCompleted()){
if(this.isCancelled())//是否暂停
return null;
if(running < maxthread){
DownloadPictureWorker2 worker = new DownloadPictureWorker2(pic);
running ++;
worker.execute();
Boolean result = worker.get();
if(result != null && result){
}else if(result == null){
return null;//暂停
}
}else{
break;
}
}
}
//整个过程下来,如果没有下载完成,则递归
if(task.getCurrent() < pics.size()){
if(this.isCancelled())//是否暂停
return null;
//是否达到下载区间要求,达到则暂停
if(success == requireNum){
Tracker.println(DownloadWorker.class, "【" + task.getName() + ":完成配置区间下载。】");
//设置任务状态为已暂停
task.setStatus(TaskStatus.STOPED);
table.setRunningNum(table.getRunningNum() - 1);//当前运行的任务数-1
//开始任务等待列表中的第一个任务
table.startWaitingTask();
table.updateUI();
return null;
}
if(exceptionNum >= requireNum){
Tracker.println(DownloadWorker.class, "【" + task.getName() + ":配额不足或者下载异常,停止下载。】");
//设置任务状态为已暂停
task.setStatus(TaskStatus.STOPED);
table.setRunningNum(table.getRunningNum() - 1);//当前运行的任务数-1
//开始任务等待列表中的第一个任务
table.startWaitingTask();
table.updateUI();
return null;
}
doInBackground();
}else{
//设置任务状态为已完成
task.setStatus(TaskStatus.COMPLETED);
Tracker.println(DownloadWorker.class ,"【" + task.getName() + "已下载完毕。】");
task.setCompletedTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
//更新任务到文件
((EgDownloaderWindow)mainWindow).taskDbTemplate.update(task);
table.setRunningNum(table.getRunningNum() - 1);//当前运行的任务数-1
//开始任务等待列表中的第一个任务
table.startWaitingTask();
table.updateUI();
}
}
return null;
}
/**
* 返回真则下载完成,返回false则下载没完成,返回null,则暂停
* @return Boolean
*/
private Boolean download(Picture pic){
requireNum ++;
try{
if(this.isCancelled())//是否暂停
return null;
if(setting.isOpenScript()){
pic.setRealUrl(ScriptParser.getdownloadUrl(task.getName(), pic.getUrl(), setting));
}else{
//pic.setRealUrl(ParseEngine.getdownloadUrl(task.getName(), pic.getUrl(), setting));
}
if(pic.getRealUrl() == null){
exceptionNum ++;
return false;
}
if(this.isCancelled())//是否暂停
return null;
InputStream is = WebClient.getStreamUseJava(pic.getRealUrl());
if(this.isCancelled())//是否暂停
return null;
int size = is.available();
if(size < 1000){
pic.setRealUrl(null);
Tracker.println(task.getName() + ":" + pic.getName() + ":403");
is.close();
exceptionNum ++;
return false;
}else if(size < 1010){
pic.setRealUrl(null);
Tracker.println(task.getName() + ":" + pic.getName() + ":509");
is.close();
exceptionNum ++;
return false;
}
String name = pic.getName();
//是否以真实名称保存,是的话则要判断是否重复并处理
if(! setting.isSaveAsName()){
if(name.indexOf(".") != -1){
name = pic.getNum() + name.substring(name.lastIndexOf("."), name.length());
}
}else{
File existNameFs = new File(ComponentConst.getSavePathPreffix() + task.getSaveDir() + "/" + name);
//已存在相同名称的文件
while(existNameFs.exists()){
name = name.substring(0, name.lastIndexOf(".")) + "_" + name.substring(name.lastIndexOf("."), name.length());
existNameFs = new File(ComponentConst.getSavePathPreffix() + task.getSaveDir() + "/" + name);
}
existNameFs = null;
}
size = FileUtil.storeStream(ComponentConst.getSavePathPreffix() + task.getSaveDir(), name, is);//保存到目录
if(this.isCancelled())//是否暂停
return null;
//Picture [id=41b2c042-7560-422b-a521-e76b56720a77, num=01, name=P213_.jpg, url=http://exhentai.org/s/b0f5fe0e5c/698928-1, realUrl=http://36.233.48.163:8888/h/b0f5fe0e5c10d164456ed3f2000d8b0ef258ab5d-1385766-1279-1850-jpg/keystamp=1401206100-f2b9d0361c/P213_.jpg, size=0, time=null, saveAsName=true, isCompleted=false, isRunning=false]
pic.setSize(size);//设置图片大小
pic.setTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));//下载完成时间
pic.setCompleted(true);//设置为已下载完成
task.setCurrent(task.getCurrent() + 1);//更新task的已下载数
//保存数据
if(this.isCancelled())//是否暂停
return null;
//更新图片信息
((EgDownloaderWindow)mainWindow).pictureDbTemplate.update(pic);
//设置最后下载时间
setting.setLastDownloadTime(pic.getTime());
Tracker.println(DownloadWorker.class ,task.getName() + ":" + pic.getName() + "下载完成。");
success ++;
running --;
table.updateUI();//完成
return true;
}catch (SocketTimeoutException e){
//碰到异常
Tracker.println(task.getName() + ":" + pic.getName() + "-读取流超时,滞后重试");
//继续下一个
return false;
}catch (ConnectTimeoutException e){
//碰到异常
Tracker.println(task.getName() + ":" + pic.getName() + "-连接超时,滞后重试");
//继续下一个
return false;
}catch (Exception e){
//碰到异常
Tracker.println(task.getName() + ":" + pic.getName() + e.getMessage());
//继续下一个
return false;
}
}
public Task getTask() {
return task;
}
/**
* 下载图片的线程类,用于开启任务内的多线程下载
* @author dipoo
* @since 2015-01-09
*/
public class DownloadPictureWorker2 extends SwingWorker<Boolean, Boolean> {
Picture pic;
public DownloadPictureWorker2(Picture pic){
this.pic = pic;
}
protected Boolean doInBackground() throws Exception {
return download(pic);
}
}
}