use of lee.study.down.model.TaskInfo in project proxyee-down by monkeyWie.
the class HttpDownInitializer method initChannel.
@Override
protected void initChannel(Channel ch) throws Exception {
if (bootstrap.getHttpDownInfo().getProxyConfig() != null) {
ch.pipeline().addLast(ProxyHandleFactory.build(bootstrap.getHttpDownInfo().getProxyConfig()));
}
if (isSsl) {
ch.pipeline().addLast(bootstrap.getClientSslContext().newHandler(ch.alloc()));
}
ch.pipeline().addLast("httpCodec", new HttpClientCodec());
ch.pipeline().addLast(new ChannelInboundHandlerAdapter() {
private Closeable closeable;
private TaskInfo taskInfo = bootstrap.getHttpDownInfo().getTaskInfo();
private HttpDownCallback callback = bootstrap.getCallback();
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
try {
if (msg instanceof HttpContent) {
if (!isSucc) {
return;
}
HttpContent httpContent = (HttpContent) msg;
ByteBuf byteBuf = httpContent.content();
synchronized (chunkInfo) {
Channel nowChannel = bootstrap.getChannel(chunkInfo);
if (chunkInfo.getStatus() == HttpDownStatus.RUNNING && nowChannel == ctx.channel()) {
int readableBytes = bootstrap.doFileWriter(chunkInfo, byteBuf.nioBuffer());
if (readableBytes > 0) {
// 最后一次下载时间
chunkInfo.setLastDownTime(System.currentTimeMillis());
// 文件已下载大小
chunkInfo.setDownSize(chunkInfo.getDownSize() + readableBytes);
taskInfo.setDownSize(taskInfo.getDownSize() + readableBytes);
if (callback != null) {
callback.onProgress(bootstrap.getHttpDownInfo(), chunkInfo);
}
}
} else {
safeClose(ctx.channel());
return;
}
}
if (isDone(chunkInfo.getDownSize(), httpContent)) {
LOGGER.debug("分段下载完成:channelId[" + ctx.channel().id() + "]\t" + chunkInfo);
bootstrap.close(chunkInfo, true);
// 分段下载完成回调
chunkInfo.setStatus(HttpDownStatus.DONE);
taskInfo.refresh(chunkInfo);
if (callback != null) {
callback.onChunkDone(bootstrap.getHttpDownInfo(), chunkInfo);
}
synchronized (taskInfo) {
if (taskInfo.getStatus() == HttpDownStatus.RUNNING && taskInfo.getChunkInfoList().stream().allMatch((chunk) -> chunk.getStatus() == HttpDownStatus.DONE)) {
if (!taskInfo.isSupportRange()) {
// chunked编码最后更新文件大小
taskInfo.setTotalSize(taskInfo.getDownSize());
taskInfo.getChunkInfoList().get(0).setTotalSize(taskInfo.getDownSize());
}
// 文件下载完成回调
taskInfo.setStatus(HttpDownStatus.DONE);
LOGGER.debug("下载完成:channelId[" + ctx.channel().id() + "]\t" + chunkInfo);
bootstrap.close(true);
if (callback != null) {
callback.onDone(bootstrap.getHttpDownInfo());
}
}
}
} else if (isContinue(chunkInfo.getDownSize())) {
// 百度响应做了手脚,会少一个字节
// 真实响应字节小于要下载的字节,在下载完成后要继续下载
LOGGER.debug("继续下载:channelId[" + ctx.channel().id() + "]\t" + chunkInfo);
bootstrap.retryChunkDown(chunkInfo, HttpDownStatus.CONNECTING_CONTINUE);
}
} else {
HttpResponse httpResponse = (HttpResponse) msg;
Integer responseCode = httpResponse.status().code();
if (responseCode.toString().indexOf("20") != 0) {
// 应对百度近期同一时段多个连接返回400的问题
LOGGER.debug("响应状态码异常:" + responseCode + "\t" + chunkInfo);
if (responseCode == 401 || responseCode == 403 || responseCode == 404) {
chunkInfo.setStatus(HttpDownStatus.ERROR_WAIT_CONNECT);
}
return;
}
realContentSize = HttpDownUtil.getDownContentSize(httpResponse.headers());
synchronized (chunkInfo) {
// 判断状态是否为连接中
if (chunkInfo.getStatus() == HttpDownStatus.CONNECTING_NORMAL || chunkInfo.getStatus() == HttpDownStatus.CONNECTING_FAIL || chunkInfo.getStatus() == HttpDownStatus.CONNECTING_CONTINUE) {
LOGGER.debug("下载响应:channelId[" + ctx.channel().id() + "]\t contentSize[" + realContentSize + "]" + chunkInfo);
chunkInfo.setDownSize(chunkInfo.getNowStartPosition() - chunkInfo.getOriStartPosition());
closeable = bootstrap.initFileWriter(chunkInfo);
chunkInfo.setStatus(HttpDownStatus.RUNNING);
if (callback != null) {
callback.onChunkConnected(bootstrap.getHttpDownInfo(), chunkInfo);
}
isSucc = true;
} else {
safeClose(ctx.channel());
}
}
}
} catch (Exception e) {
throw e;
} finally {
ReferenceCountUtil.release(msg);
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
LOGGER.error("down onChunkError:", cause);
Channel nowChannel = bootstrap.getChannel(chunkInfo);
safeClose(ctx.channel());
if (nowChannel == ctx.channel()) {
if (callback != null) {
callback.onChunkError(bootstrap.getHttpDownInfo(), chunkInfo, cause);
}
bootstrap.retryChunkDown(chunkInfo);
}
}
@Override
public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
super.channelUnregistered(ctx);
safeClose(ctx.channel());
}
private void safeClose(Channel channel) {
try {
HttpDownUtil.safeClose(channel, closeable);
} catch (IOException e) {
LOGGER.error("safeClose fail:", e);
}
}
private boolean isDone(long downSize, HttpContent content) {
return downSize == chunkInfo.getTotalSize() || (!taskInfo.isSupportRange() && content instanceof LastHttpContent);
}
private boolean isContinue(long downSize) {
long downChunkSize = downSize + chunkInfo.getOriStartPosition() - chunkInfo.getNowStartPosition();
return realContentSize == downChunkSize || (realContentSize - 1) == downChunkSize;
}
});
}
use of lee.study.down.model.TaskInfo in project proxyee-down by monkeyWie.
the class DownContent method putBoot.
public void putBoot(HttpDownInfo httpDownInfo) {
AbstractHttpDownBootstrap bootstrap = HttpDownBootstrapFactory.create(httpDownInfo, ContentManager.CONFIG.get().getRetryCount(), HttpDownConstant.clientSslContext, HttpDownConstant.clientLoopGroup, HttpDownConstant.httpDownCallback);
TaskInfo taskInfo = bootstrap.getHttpDownInfo().getTaskInfo();
if (taskInfo.isSupportRange()) {
taskInfo.setConnections(ContentManager.CONFIG.get().getConnections());
}
taskInfo.setFilePath(ContentManager.CONFIG.get().getLastPath());
putBoot(bootstrap);
}
use of lee.study.down.model.TaskInfo in project proxyee-down by monkeyWie.
the class DownContent method buildWsForm.
public WsForm buildWsForm(String taskId) {
List<TaskInfo> list = new ArrayList<>();
TaskInfo taskInfo = getTaskInfo(taskId);
if (taskInfo == null) {
return null;
} else {
list.add(taskInfo);
return new WsForm(WsDataType.TASK_LIST, setUrl(list));
}
}
use of lee.study.down.model.TaskInfo in project proxyee-down by monkeyWie.
the class HttpDownHandleCallback method onDone.
@Override
public void onDone(HttpDownInfo httpDownInfo) throws Exception {
TaskInfo taskInfo = httpDownInfo.getTaskInfo();
// 更改任务下载状态为已完成
ContentManager.DOWN.save();
// 删除任务进度记录文件
synchronized (taskInfo) {
FileUtil.deleteIfExists(taskInfo.buildTaskRecordFilePath());
FileUtil.deleteIfExists(taskInfo.buildTaskRecordBakFilePath());
}
sendTask(httpDownInfo.getTaskInfo().getId());
NewTaskForm taskForm = NewTaskForm.parse(httpDownInfo);
if (taskForm.isUnzip()) {
if (BdyZip.isBdyZip(taskInfo.buildTaskFilePath())) {
WsForm wsForm = new WsForm(WsDataType.UNZIP_NEW, new HashMap<String, String>() {
{
put("filePath", taskInfo.buildTaskFilePath());
put("toPath", taskForm.getUnzipPath());
}
});
ContentManager.WS.sendMsg(wsForm);
}
}
}
use of lee.study.down.model.TaskInfo in project proxyee-down by monkeyWie.
the class HttpDownController method commonStartTask.
public static ResultInfo commonStartTask(NewTaskForm taskForm) throws Exception {
ResultInfo resultInfo = new ResultInfo();
AbstractHttpDownBootstrap bootstrap = ContentManager.DOWN.getBoot(taskForm.getId());
HttpDownInfo httpDownInfo = bootstrap.getHttpDownInfo();
// 覆盖下载
if (!StringUtils.isEmpty(taskForm.getOldId())) {
AbstractHttpDownBootstrap oldBootstrap = ContentManager.DOWN.getBoot(taskForm.getOldId());
if (oldBootstrap == null) {
resultInfo.setStatus(ResultStatus.BAD.getCode()).setMsg("任务不存在");
return resultInfo;
} else {
// 暂停之前的下载任务
oldBootstrap.pauseDown();
// 修改request
oldBootstrap.getHttpDownInfo().setRequest(httpDownInfo.getRequest());
oldBootstrap.getHttpDownInfo().setProxyConfig(httpDownInfo.getProxyConfig());
Map<String, Object> attr = oldBootstrap.getHttpDownInfo().getAttrs();
if (attr == null) {
attr = new HashMap<>();
oldBootstrap.getHttpDownInfo().setAttrs(attr);
}
attr.put(NewTaskForm.KEY_UNZIP_FLAG, taskForm.isUnzip());
attr.put(NewTaskForm.KEY_UNZIP_PATH, taskForm.getUnzipPath());
// 移除新的下载任务
ContentManager.DOWN.removeBoot(taskForm.getId());
// 持久化
ContentManager.DOWN.save();
// 用新链接继续下载
oldBootstrap.continueDown();
}
} else {
if (StringUtils.isEmpty(taskForm.getFileName())) {
resultInfo.setStatus(ResultStatus.BAD.getCode()).setMsg("文件名不能为空");
return resultInfo;
}
if (StringUtils.isEmpty(taskForm.getFilePath())) {
resultInfo.setStatus(ResultStatus.BAD.getCode()).setMsg("路径不能为空");
return resultInfo;
}
buildDefaultValues(taskForm);
TaskInfo taskInfo = httpDownInfo.getTaskInfo();
synchronized (taskInfo) {
if (taskInfo.getStatus() != HttpDownStatus.WAIT) {
resultInfo.setStatus(ResultStatus.BAD.getCode()).setMsg("任务已添加至下载列表");
}
taskInfo.setFileName(taskForm.getFileName());
taskInfo.setFilePath(taskForm.getFilePath());
Map<String, Object> attr = httpDownInfo.getAttrs();
if (attr == null) {
attr = new HashMap<>();
httpDownInfo.setAttrs(attr);
}
attr.put(NewTaskForm.KEY_UNZIP_FLAG, taskForm.isUnzip());
attr.put(NewTaskForm.KEY_UNZIP_PATH, taskForm.getUnzipPath());
if (taskInfo.isSupportRange()) {
taskInfo.setConnections(taskForm.getConnections());
} else {
taskInfo.setConnections(1);
}
try {
bootstrap.startDown();
} catch (BootstrapException e) {
resultInfo.setStatus(ResultStatus.BAD.getCode()).setMsg(e.getMessage());
return resultInfo;
}
// 记录存储路径
String lastPath = ContentManager.CONFIG.get().getLastPath();
if (!taskForm.getFilePath().equalsIgnoreCase(lastPath)) {
ContentManager.CONFIG.get().setLastPath(taskForm.getFilePath());
ContentManager.CONFIG.save();
}
}
}
return resultInfo;
}
Aggregations