feat(download): 支持分区存储Uri下载模式

This commit is contained in:
2026-07-27 01:38:57 +08:00
parent cb50a2dcd2
commit cef92d6a2f
25 changed files with 1037 additions and 54 deletions

View File

@@ -19,7 +19,7 @@ import android.net.TrafficStats;
import android.net.Uri;
import android.os.Process;
import android.text.TextUtils;
import android.util.Log;
import com.arialyy.aria.core.AriaConfig;
import com.arialyy.aria.core.common.CompleteInfo;
import com.arialyy.aria.core.common.RequestEnum;
@@ -36,6 +36,7 @@ import com.arialyy.aria.util.CheckUtil;
import com.arialyy.aria.util.CommonUtil;
import com.arialyy.aria.util.FileUtil;
import com.arialyy.aria.util.RecordUtil;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
@@ -146,7 +147,9 @@ final class HttpDFileInfoTask implements IInfoTask, Runnable {
}
long len = lenAdapter.handleFileLen(conn.getHeaderFields());
if (!FileUtil.checkMemorySpace(mEntity.getFilePath(), len)) {
// 分区存储 Uri 任务写入的是 UriSAF / MediaStore不校验本地存储空间
if (TextUtils.isEmpty(mEntity.getFileUri())
&& !FileUtil.checkMemorySpace(mEntity.getFilePath(), len)) {
failDownload(new AriaHTTPException(
String.format("下载失败内存空间不足filePath: %s, url: %s", mEntity.getFilePath(),
mEntity.getUrl())), false);
@@ -307,6 +310,12 @@ final class HttpDFileInfoTask implements IInfoTask, Runnable {
ALog.w(TAG, "重命名失败【服务器返回的文件名为空】");
return;
}
// 分区存储 Uri 任务写入的是 Uri不支持重命名本地文件仅使用服务器文件名作为展示名
if (!TextUtils.isEmpty(mEntity.getFileUri())) {
ALog.d(TAG, String.format("Uri 任务直接使用服务器文件名:%s", newName));
mEntity.setFileName(newName);
return;
}
ALog.d(TAG, String.format("文件重命名为:%s", newName));
File oldFile = new File(mEntity.getFilePath());
String newPath = oldFile.getParent() + "/" + newName;

View File

@@ -8,6 +8,7 @@ import com.arialyy.aria.core.task.IThreadTaskAdapter;
import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.BufferedRandomAccessFile;
import com.arialyy.aria.util.FileUtil;
import java.io.File;
import java.io.IOException;
@@ -18,6 +19,10 @@ final class HttpDTTBuilderAdapter extends AbsNormalTTBuilderAdapter {
}
@Override public boolean handleNewTask(TaskRecord record, int totalThreadNum) {
if (isUriMode()) {
// 分区存储Uri模式没有本地临时文件目标内容由ContentProvider管理无需清理
return true;
}
if (!record.isBlock) {
if (getTempFile().exists()) {
FileUtil.deleteFile(getTempFile());

View File

@@ -15,6 +15,7 @@
*/
package com.arialyy.aria.http.download;
import com.arialyy.aria.core.AriaConfig;
import com.arialyy.aria.core.common.RequestEnum;
import com.arialyy.aria.core.common.SubThreadConfig;
import com.arialyy.aria.core.download.DTaskWrapper;
@@ -23,6 +24,8 @@ import com.arialyy.aria.http.BaseHttpThreadTaskAdapter;
import com.arialyy.aria.http.ConnectionHelp;
import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.BufferedRandomAccessFile;
import com.arialyy.aria.util.UriRandomAccessFile;
import java.io.BufferedInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
@@ -100,6 +103,29 @@ final class HttpDThreadTaskAdapter extends BaseHttpThreadTaskAdapter {
}
is = new BufferedInputStream(ConnectionHelp.convertInputStream(conn));
if (getThreadConfig().tempUri != null) {
// 分区存储:通过 Uri 写入,支持断点续传
UriRandomAccessFile uriFile = null;
try {
uriFile = new UriRandomAccessFile(AriaConfig.getInstance().getAPP(),
getThreadConfig().tempUri, getThreadRecord().startLocation);
readNormal(is, uriFile);
handleComplete();
return;
} catch (IOException e) {
fail(new AriaHTTPException(String.format("任务【%s】通过 Uri 下载失败uri: %s, url: %s",
getFileName(), getThreadConfig().tempUri, getThreadConfig().url), e), true);
return;
} finally {
if (uriFile != null) {
try {
uriFile.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
if (mTaskOption.isChunked()) {
readChunked(is);
} else if (getThreadConfig().isBlock) {
@@ -259,6 +285,31 @@ final class HttpDThreadTaskAdapter extends BaseHttpThreadTaskAdapter {
}
}
/**
* 分区存储:通过 UriFileChannel写入数据支持断点续传
*/
private void readNormal(InputStream is, UriRandomAccessFile file) throws IOException {
byte[] buffer = new byte[getTaskConfig().getBuffSize()];
int len;
while (getThreadTask().isLive() && (len = is.read(buffer)) != -1) {
if (getThreadTask().isBreak()) {
break;
}
if (mSpeedBandUtil != null) {
mSpeedBandUtil.limitNextBytes(len);
}
if (getThreadRecord().endLocation > 0
&& getRangeProgress() + len >= getThreadRecord().endLocation) {
len = (int) (getThreadRecord().endLocation - getRangeProgress());
file.write(buffer, 0, len);
progress(len);
break;
}
file.write(buffer, 0, len);
progress(len);
}
}
/**
* 处理完成配置文件的更新或事件回调
*/