diff --git a/.github/workflows/ci-test.yml b/.github/workflows/ci-test.yml
index 2d4042f2f..5fc827f36 100644
--- a/.github/workflows/ci-test.yml
+++ b/.github/workflows/ci-test.yml
@@ -18,6 +18,8 @@ jobs:
uses: reactivecircus/android-emulator-runner@v2
with:
api-level: 22
+ profile: Nexus 6
+ arch: x86_64
script: |
./gradlew connectedCheck
./gradlew build
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1173df9ff..4cc012e77 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,9 +1,11 @@
#Changelog
+## 8.3.0(2021-05-12)
+* 支持资源通过 Uri 和 InputStream 方式上传
+
## 8.2.1(2021-04-14)
* 优化分片上传逻辑,增加重试
## 8.2.0(2021-02-20)
-## 增加
* 增加网络监控功能,选择最优 Host 进行上传
* 优化日志统计
diff --git a/README.md b/README.md
index 202bcb715..0f6f87aed 100644
--- a/README.md
+++ b/README.md
@@ -15,6 +15,7 @@ https://github.com/qiniudemo/qiniu-lab-android
| Qiniu SDK 版本 | 最低 Android版本 | 依赖库版本 |
|------------ |-----------------|------------------------|
+| 8.3.x | Android 5.0+ | okhttp 4+ |
| 8.2.x | Android 5.0+ | okhttp 4+ |
| 8.1.x | Android 5.0+ | okhttp 4+ |
| 8.0.x | Android 5.0+ | okhttp 4+ |
@@ -29,7 +30,7 @@ https://github.com/qiniudemo/qiniu-lab-android
| 7.0.7 | Android 2.2+ | android-async-http 1.4.8 |
### 注意
-* 推荐使用最新版:8.2.1
+* 推荐使用最新版:8.3.0
* AndroidNetwork.getMobileDbm()可以获取手机信号强度,需要如下权限(API>=18时生效)
```
diff --git a/library/build.gradle b/library/build.gradle
index 4be9ddc90..d108afe2f 100755
--- a/library/build.gradle
+++ b/library/build.gradle
@@ -24,7 +24,7 @@ android {
buildToolsVersion '29.0.2'
defaultConfig {
//applicationId "com.qiniu.android"
- minSdkVersion 15
+ minSdkVersion 19
targetSdkVersion 26
versionCode code
versionName version
@@ -52,7 +52,8 @@ android {
dependencies {
implementation 'com.squareup.okhttp3:okhttp:4.2.2'
- implementation 'com.qiniu:happy-dns:0.2.16'
+// implementation 'com.squareup.okhttp3:okhttp:3.12.1'
+ implementation 'com.qiniu:happy-dns:0.2.18'
// for javax.annotation.Nullable use in custom MultipartBody and Headers implements.
// implementation 'com.google.code.findbugs:jsr305:3.0.2'
implementation 'org.conscrypt:conscrypt-android:2.2.1'
diff --git a/library/library.iml b/library/library.iml
index cff9603ba..244cd7b6d 100644
--- a/library/library.iml
+++ b/library/library.iml
@@ -97,7 +97,7 @@
-
+
diff --git a/library/src/androidTest/java/com/qiniu/android/ComplexUploadSceneTest.java b/library/src/androidTest/java/com/qiniu/android/ComplexUploadSceneTest.java
index c9085459f..d97cda069 100644
--- a/library/src/androidTest/java/com/qiniu/android/ComplexUploadSceneTest.java
+++ b/library/src/androidTest/java/com/qiniu/android/ComplexUploadSceneTest.java
@@ -48,7 +48,9 @@ public void testMutiUploadV1(){
continue;
}
- uploadFile(file, keyUp, config, null, new UpCompletionHandler() {
+ UploadInfo info = new UploadInfo<>(file);
+ info.configWithFile(file);
+ upload(info, keyUp, config, null, new UpCompletionHandler() {
@Override
public void complete(String key, ResponseInfo info, JSONObject response) {
synchronized (param){
@@ -100,7 +102,9 @@ public void testMutiUploadV2(){
continue;
}
- uploadFile(file, keyUp, config, null, new UpCompletionHandler() {
+ UploadInfo info = new UploadInfo<>(file);
+ info.configWithFile(file);
+ upload(info, keyUp, config, null, new UpCompletionHandler() {
@Override
public void complete(String key, ResponseInfo info, JSONObject response) {
synchronized (param){
diff --git a/library/src/androidTest/java/com/qiniu/android/ConcurrentResumeUploadTest.java b/library/src/androidTest/java/com/qiniu/android/ConcurrentResumeUploadTest.java
index b4aac0667..73edb1a1a 100644
--- a/library/src/androidTest/java/com/qiniu/android/ConcurrentResumeUploadTest.java
+++ b/library/src/androidTest/java/com/qiniu/android/ConcurrentResumeUploadTest.java
@@ -60,7 +60,7 @@ public void testCancelV1() {
String key = "android_concurrent_resume_cancel_v1_" + size + "k";
try {
File file = TempFile.createFile(size, key);
- cancelTest(cancelPercent, file, key, configuration, null);
+ cancelTest((long) (size * cancelPercent), file, key, configuration, null);
TempFile.remove(file);
} catch (IOException e) {
e.printStackTrace();
@@ -68,7 +68,7 @@ public void testCancelV1() {
}
}
- public void testHttpV1(){
+ public void testHttpV1() {
Configuration configuration = new Configuration.Builder()
.resumeUploadVersion(Configuration.RESUME_UPLOAD_VERSION_V1)
.useConcurrentResumeUpload(true)
@@ -87,7 +87,7 @@ public void testHttpV1(){
}
}
- public void testHttpsV1(){
+ public void testHttpsV1() {
Configuration configuration = new Configuration.Builder()
.resumeUploadVersion(Configuration.RESUME_UPLOAD_VERSION_V1)
.useConcurrentResumeUpload(true)
@@ -106,19 +106,19 @@ public void testHttpsV1(){
}
}
- public void testReuploadV1(){
+ public void testReuploadV1() {
Configuration configuration = new Configuration.Builder()
.resumeUploadVersion(Configuration.RESUME_UPLOAD_VERSION_V1)
.useConcurrentResumeUpload(true)
.useHttps(true)
- .chunkSize(1024*1024)
+ .chunkSize(1024 * 1024)
.build();
int[] sizeArray = {30000};
for (int size : sizeArray) {
String key = "android_concurrent_resume_reupload_v1_" + size + "k";
try {
File file = TempFile.createFile(size, key);
- reuploadUploadTest((float)0.7, file, key, configuration, null);
+ reuploadUploadTest((long) (size * 0.7), file, key, configuration, null);
TempFile.remove(file);
} catch (IOException e) {
e.printStackTrace();
@@ -126,7 +126,7 @@ public void testReuploadV1(){
}
}
- public void testNoKeyV1(){
+ public void testNoKeyV1() {
int size = 600;
String key = "android_concurrent_resume_no_key_v1_" + size + "k";
File file = null;
@@ -153,7 +153,7 @@ public void testNoKeyV1(){
TempFile.remove(file);
}
- public void test0kV1(){
+ public void test0kV1() {
int size = 0;
String key = "android_concurrent_resume_0k_v1_" + size + "k";
File file = null;
@@ -185,7 +185,7 @@ public void testSwitchRegionV2() {
Configuration configuration = new Configuration.Builder()
.resumeUploadVersion(Configuration.RESUME_UPLOAD_VERSION_V2)
.useConcurrentResumeUpload(true)
- .chunkSize(4*1024*1024)
+ .chunkSize(4 * 1024 * 1024)
.useHttps(true)
.build();
int[] sizeArray = {5000, 8000, 10000, 20000};
@@ -206,7 +206,7 @@ public void testCancelV2() {
Configuration configuration = new Configuration.Builder()
.resumeUploadVersion(Configuration.RESUME_UPLOAD_VERSION_V2)
.useConcurrentResumeUpload(true)
- .chunkSize(4*1024*1024)
+ .chunkSize(4 * 1024 * 1024)
.useHttps(true)
.build();
int[] sizeArray = {10000, 20000};
@@ -214,7 +214,7 @@ public void testCancelV2() {
String key = "android_concurrent_resume_cancel_v2_" + size + "k";
try {
File file = TempFile.createFile(size, key);
- cancelTest(cancelPercent, file, key, configuration, null);
+ cancelTest((long) (size * cancelPercent), file, key, configuration, null);
TempFile.remove(file);
} catch (IOException e) {
e.printStackTrace();
@@ -222,14 +222,14 @@ public void testCancelV2() {
}
}
- public void testHttpV2(){
+ public void testHttpV2() {
Configuration configuration = new Configuration.Builder()
.resumeUploadVersion(Configuration.RESUME_UPLOAD_VERSION_V2)
.useConcurrentResumeUpload(true)
- .chunkSize(4*1024*1024)
+ .chunkSize(4 * 1024 * 1024)
.useHttps(false)
.build();
- int[] sizeArray = {500, 1000, 3000, 4000, 5000, 8000, 10000, 20000};
+ int[] sizeArray = {500, 2000, 4000, 5000, 8000, 20000};
long timestamp = new Date().getTime();
for (int size : sizeArray) {
String key = "android_concurrent_resume_http_v2_" + timestamp + "_" + size + "k";
@@ -243,14 +243,14 @@ public void testHttpV2(){
}
}
- public void testHttpsV2(){
+ public void testHttpsV2() {
Configuration configuration = new Configuration.Builder()
.resumeUploadVersion(Configuration.RESUME_UPLOAD_VERSION_V2)
.useConcurrentResumeUpload(true)
.useHttps(true)
- .chunkSize(4*1024*1024)
+ .chunkSize(4 * 1024 * 1024)
.build();
- int[] sizeArray = {500, 1000, 3000, 4000, 5000, 8000, 10000, 20000};
+ int[] sizeArray = {500, 2000, 4000, 5000, 8000, 20000};
for (int size : sizeArray) {
String key = "android_concurrent_resume_https_v2_" + size + "k";
try {
@@ -263,19 +263,19 @@ public void testHttpsV2(){
}
}
- public void testReuploadV2(){
+ public void testReuploadV2() {
Configuration configuration = new Configuration.Builder()
.resumeUploadVersion(Configuration.RESUME_UPLOAD_VERSION_V2)
.useConcurrentResumeUpload(true)
.useHttps(true)
- .chunkSize(4*1024*1024)
+ .chunkSize(4 * 1024 * 1024)
.build();
int[] sizeArray = {30000};
for (int size : sizeArray) {
String key = "android_concurrent_resume_reupload_v2_" + size + "k";
try {
File file = TempFile.createFile(size, key);
- reuploadUploadTest((float)0.7, file, key, configuration, null);
+ reuploadUploadTest((long) (size * 0.7), file, key, configuration, null);
TempFile.remove(file);
} catch (IOException e) {
e.printStackTrace();
@@ -283,7 +283,7 @@ public void testReuploadV2(){
}
}
- public void testNoKeyV2(){
+ public void testNoKeyV2() {
int size = 600;
String key = "android_concurrent_resume_no_key_v2_" + size + "k";
File file = null;
@@ -310,7 +310,7 @@ public void testNoKeyV2(){
TempFile.remove(file);
}
- public void test0kV2(){
+ public void test0kV2() {
int size = 0;
String key = "android_concurrent_resume_0k_v2_" + size + "k";
File file = null;
diff --git a/library/src/androidTest/java/com/qiniu/android/FormUploadTest.java b/library/src/androidTest/java/com/qiniu/android/FormUploadTest.java
index 5d3d01bd2..693d996fc 100644
--- a/library/src/androidTest/java/com/qiniu/android/FormUploadTest.java
+++ b/library/src/androidTest/java/com/qiniu/android/FormUploadTest.java
@@ -6,6 +6,8 @@
import com.qiniu.android.storage.Configuration;
import com.qiniu.android.storage.UploadOptions;
+import junit.framework.Assert;
+
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
@@ -20,9 +22,14 @@ public void testSwitchRegion() {
.build();
int[] sizeArray = {5, 50, 200, 500, 800, 1000, 2000, 3000, 4000};
for (int size : sizeArray) {
- String key = "android_form_switch_region_" + size + "k";
- byte[] data = TempFile.getByte(size);
- switchRegionTestWithData(data, key, configuration, null);
+ String key = "android_Form_switch_region_" + size + "k";
+ File file = null;
+ try {
+ file = TempFile.createFile(size, key);
+ } catch (IOException e) {
+ Assert.assertTrue(e.getMessage(), false);
+ }
+ switchRegionTestWithFile(file, key, configuration, null);
}
}
@@ -35,12 +42,17 @@ public void testCancel() {
int[] sizeArray = {2000, 3000, 4000};
for (int size : sizeArray) {
String key = "android_form_cancel_" + size + "k";
- byte[] data = TempFile.getByte(size*1024);
- cancelTest(cancelPercent, data, key, configuration, null);
+ File file = null;
+ try {
+ file = TempFile.createFile(size, key);
+ } catch (IOException e) {
+ Assert.fail(e.getMessage());
+ }
+ cancelTest((long) (size * cancelPercent), file, key, configuration, null);
}
}
- public void testHttpV1() {
+ public void testHttp() {
Configuration configuration = new Configuration.Builder()
.resumeUploadVersion(Configuration.RESUME_UPLOAD_VERSION_V1)
.useConcurrentResumeUpload(true)
@@ -48,13 +60,18 @@ public void testHttpV1() {
.build();
int[] sizeArray = {500, 1000, 3000, 4000, 5000, 8000, 10000, 20000};
for (int size : sizeArray) {
- String key = "android_form_http_v1_" + size + "k";
- byte[] data = TempFile.getByte(size);
- uploadDataAndAssertSuccessResult(data, key, configuration, null);
+ String key = "android_form_http" + size + "k";
+ File file = null;
+ try {
+ file = TempFile.createFile(size, key);
+ } catch (IOException e) {
+ Assert.assertTrue(e.getMessage(), false);
+ }
+ uploadFileAndAssertSuccessResult(file, key, configuration, null);
}
}
- public void testHttpsV1() {
+ public void testHttps() {
Configuration configuration = new Configuration.Builder()
.resumeUploadVersion(Configuration.RESUME_UPLOAD_VERSION_V1)
.useConcurrentResumeUpload(true)
@@ -62,9 +79,14 @@ public void testHttpsV1() {
.build();
int[] sizeArray = {500, 1000, 3000, 4000, 5000, 8000, 10000, 20000};
for (int size : sizeArray) {
- String key = "android_form_https_v1_" + size + "k";
- byte[] data = TempFile.getByte(size);
- uploadDataAndAssertSuccessResult(data, key, configuration, null);
+ String key = "android_form_https" + size + "k";
+ File file = null;
+ try {
+ file = TempFile.createFile(size, key);
+ } catch (IOException e) {
+ Assert.assertTrue(e.getMessage(), false);
+ }
+ uploadFileAndAssertSuccessResult(file, key, configuration, null);
}
}
@@ -75,51 +97,67 @@ public void testSmall() {
//mime type
final String mimeType = "text/plain";
final UploadOptions options = new UploadOptions(params, mimeType, true, null, null);
- byte[] data = "Hello, World!".getBytes();
- uploadDataAndAssertSuccessResult(data, "android_你好", null, options);
+
+ String key = "android_small";
+ File file = null;
+ try {
+ file = TempFile.createFile(10, key);
+ } catch (IOException e) {
+ Assert.assertTrue(e.getMessage(), false);
+ }
+ uploadFileAndAssertSuccessResult(file, key, null, options);
}
public void test100up() {
int count = 100;
for (int i = 1; i < count; i++) {
- String key = "android_form_100_up_" + i + "k";
- byte[] data = TempFile.getByte(i * 1024);
- uploadDataAndAssertSuccessResult(data, key, null, null);
+ String key = "android_form_100_UP_" + i + "k";
+ File file = null;
+ try {
+ file = TempFile.createFile(10, key);
+ } catch (IOException e) {
+ Assert.assertTrue(e.getMessage(), false);
+ }
+ uploadFileAndAssertSuccessResult(file, key, null, null);
}
}
public void testUpUnAuth() {
- byte[] data = "Hello, World!".getBytes();
- uploadDataAndAssertResult(ResponseInfo.InvalidToken, data, "noAuth", "android_form_no_auth", null, null);
+ String key = "android_unAuth";
+ File file = null;
+ try {
+ file = TempFile.createFile(10, key);
+ } catch (IOException e) {
+ Assert.assertTrue(e.getMessage(), false);
+ }
+ uploadFileAndAssertResult(ResponseInfo.InvalidToken, file, "noAuth", "android_form_no_auth", null, null);
}
public void testNoData() {
- uploadDataAndAssertResult(ResponseInfo.ZeroSizeFile, null, "android_form_no_data", null, null);
- }
-
- public void testNoFile() {
- uploadFileAndAssertResult(ResponseInfo.ZeroSizeFile, null, "android_form_no_file", null, null);
+ String key = "android_noData";
+ File file = null;
+ try {
+ file = TempFile.createFile(0, key);
+ } catch (IOException e) {
+ Assert.assertTrue(e.getMessage(), false);
+ }
+ uploadFileAndAssertResult(ResponseInfo.ZeroSizeFile, file, key, null, null);
}
public void testNoToken() {
String key = "android_form_no_token";
File file = null;
- byte[] data = null;
try {
file = TempFile.createFile(5 * 1024, key);
- data = TempFile.getByte(5 * 1024);
} catch (IOException e) {
e.printStackTrace();
}
- uploadDataAndAssertResult(ResponseInfo.InvalidToken, data, null, key, null, null);
uploadFileAndAssertResult(ResponseInfo.InvalidToken, file, null, key, null, null);
- uploadDataAndAssertResult(ResponseInfo.InvalidToken, data, "", key, null, null);
uploadFileAndAssertResult(ResponseInfo.InvalidToken, file, "", key, null, null);
- uploadDataAndAssertResult(ResponseInfo.InvalidToken, data, "ABC", key, null, null);
uploadFileAndAssertResult(ResponseInfo.InvalidToken, file, "ABC", key, null, null);
TempFile.remove(file);
@@ -128,28 +166,22 @@ public void testNoToken() {
public void testNoKey() {
String key = "android_form_no_key";
File file = null;
- byte[] data = null;
try {
file = TempFile.createFile(5 * 1024, key);
- data = TempFile.getByte(5 * 1024);
} catch (IOException e) {
e.printStackTrace();
}
- uploadDataAndAssertSuccessResult(data, null, null, null);
uploadFileAndAssertSuccessResult(file, null, null, null);
TempFile.remove(file);
}
public void testUrlConvert() {
- String dataKey = "android_form_url_convert_data_new";
String fileKey = "android_form_url_convert_file_new";
File file = null;
- byte[] data = null;
try {
file = TempFile.createFile(5, fileKey);
- data = TempFile.getByte(5 * 1024);
} catch (IOException e) {
e.printStackTrace();
}
@@ -160,11 +192,10 @@ public void testUrlConvert() {
.urlConverter(new UrlConverter() {
@Override
public String convert(String url) {
- return url.replace("upnono", "up");
+ return url.replace("upnono", "up");
}
})
.build();
- uploadDataAndAssertSuccessResult(data, dataKey, configuration, null);
uploadFileAndAssertSuccessResult(file, fileKey, configuration, null);
}
@@ -179,20 +210,15 @@ public void testCustomParam() {
metaParam.put("x-qn-meta-aaa", "meta_value_1");
metaParam.put("x-qn-meta-key-2", "meta_value_2");
- UploadOptions options = new UploadOptions(userParam, metaParam, null,true, null, null, null);
+ UploadOptions options = new UploadOptions(userParam, metaParam, null, true, null, null, null);
- String dataKey = "android_form_custom_param_data";
String fileKey = "android_form_custom_param_file";
File file = null;
- byte[] data = null;
try {
file = TempFile.createFile(5, fileKey);
- data = TempFile.getByte(5 * 1024);
} catch (IOException e) {
e.printStackTrace();
}
-
- uploadDataAndAssertSuccessResult(data, dataKey, null, options);
uploadFileAndAssertSuccessResult(file, fileKey, null, options);
}
diff --git a/library/src/androidTest/java/com/qiniu/android/ResumeUploadTest.java b/library/src/androidTest/java/com/qiniu/android/ResumeUploadTest.java
index 0fdf9b146..477d70198 100644
--- a/library/src/androidTest/java/com/qiniu/android/ResumeUploadTest.java
+++ b/library/src/androidTest/java/com/qiniu/android/ResumeUploadTest.java
@@ -44,7 +44,7 @@ public void testCancelV1() {
String key = "android_resume_cancel_v1_" + size + "k";
try {
File file = TempFile.createFile(size, key);
- cancelTest(cancelPercent, file, key, configuration, null);
+ cancelTest((long) (size * cancelPercent), file, key, configuration, null);
TempFile.remove(file);
} catch (IOException e) {
e.printStackTrace();
@@ -52,7 +52,7 @@ public void testCancelV1() {
}
}
- public void testHttpV1(){
+ public void testHttpV1() {
Configuration configuration = new Configuration.Builder()
.resumeUploadVersion(Configuration.RESUME_UPLOAD_VERSION_V1)
.useConcurrentResumeUpload(false)
@@ -71,13 +71,13 @@ public void testHttpV1(){
}
}
- public void testHttpsV1(){
+ public void testHttpsV1() {
Configuration configuration = new Configuration.Builder()
.resumeUploadVersion(Configuration.RESUME_UPLOAD_VERSION_V1)
.useConcurrentResumeUpload(false)
.useHttps(true)
.build();
- int[] sizeArray = {500, 1000, 3000, 4000, 5000, 8000, 10000, 20000};
+ int[] sizeArray = {500, 3000, 4000, 7000, 10000, 20000};
for (int size : sizeArray) {
String key = "android_resume_https_v1_" + size + "k";
try {
@@ -90,19 +90,19 @@ public void testHttpsV1(){
}
}
- public void testReuploadV1(){
+ public void testReuploadV1() {
Configuration configuration = new Configuration.Builder()
.resumeUploadVersion(Configuration.RESUME_UPLOAD_VERSION_V1)
.useConcurrentResumeUpload(false)
.useHttps(true)
- .chunkSize(1024*1024)
+ .chunkSize(1024 * 1024)
.build();
int[] sizeArray = {30000};
for (int size : sizeArray) {
String key = "android_resume_reupload_v1_" + size + "k";
try {
File file = TempFile.createFile(size, key);
- reuploadUploadTest((float)0.7, file, key, configuration, null);
+ reuploadUploadTest((long) (size * 0.7), file, key, configuration, null);
TempFile.remove(file);
} catch (IOException e) {
e.printStackTrace();
@@ -110,7 +110,7 @@ public void testReuploadV1(){
}
}
- public void testNoKeyV1(){
+ public void testNoKeyV1() {
int size = 600;
String key = "android_resume_no_key_v1_" + size + "k";
File file = null;
@@ -137,7 +137,7 @@ public void testNoKeyV1(){
TempFile.remove(file);
}
- public void test0kV1(){
+ public void test0kV1() {
int size = 0;
String key = "android_resume_0k_v1_" + size + "k";
File file = null;
@@ -175,7 +175,7 @@ public void testCustomParamV1() {
metaParam.put("x-qn-meta-aaa", "meta_value_1");
metaParam.put("x-qn-meta-key-2", "meta_value_2");
- UploadOptions options = new UploadOptions(userParam, metaParam, null,true, null, null, null);
+ UploadOptions options = new UploadOptions(userParam, metaParam, null, true, null, null, null);
Configuration configuration = new Configuration.Builder()
.resumeUploadVersion(Configuration.RESUME_UPLOAD_VERSION_V1)
@@ -198,7 +198,7 @@ public void testSwitchRegionV2() {
Configuration configuration = new Configuration.Builder()
.resumeUploadVersion(Configuration.RESUME_UPLOAD_VERSION_V2)
.useConcurrentResumeUpload(false)
- .chunkSize(4*1024*1024)
+ .chunkSize(4 * 1024 * 1024)
.useHttps(true)
.build();
int[] sizeArray = {5000, 8000, 10000, 20000};
@@ -219,7 +219,7 @@ public void testCancelV2() {
Configuration configuration = new Configuration.Builder()
.resumeUploadVersion(Configuration.RESUME_UPLOAD_VERSION_V2)
.useConcurrentResumeUpload(false)
- .chunkSize(4*1024*1024)
+ .chunkSize(4 * 1024 * 1024)
.useHttps(true)
.build();
int[] sizeArray = {10000, 20000};
@@ -227,7 +227,7 @@ public void testCancelV2() {
String key = "android_resume_cancel_v2_" + size + "k";
try {
File file = TempFile.createFile(size, key);
- cancelTest(cancelPercent, file, key, configuration, null);
+ cancelTest((long) (size * cancelPercent), file, key, configuration, null);
TempFile.remove(file);
} catch (IOException e) {
e.printStackTrace();
@@ -235,11 +235,11 @@ public void testCancelV2() {
}
}
- public void testHttpV2(){
+ public void testHttpV2() {
Configuration configuration = new Configuration.Builder()
.resumeUploadVersion(Configuration.RESUME_UPLOAD_VERSION_V2)
.useConcurrentResumeUpload(false)
- .chunkSize(4*1024*1024)
+ .chunkSize(4 * 1024 * 1024)
.useHttps(false)
.build();
int[] sizeArray = {500, 1000, 3000, 4000, 5000, 8000, 10000, 20000};
@@ -255,14 +255,14 @@ public void testHttpV2(){
}
}
- public void testHttpsV2(){
+ public void testHttpsV2() {
Configuration configuration = new Configuration.Builder()
.resumeUploadVersion(Configuration.RESUME_UPLOAD_VERSION_V2)
.useConcurrentResumeUpload(false)
- .chunkSize(4*1024*1024)
+ .chunkSize(4 * 1024 * 1024)
.useHttps(true)
.build();
- int[] sizeArray = {500, 1000, 3000, 4000, 5000, 8000, 10000, 20000};
+ int[] sizeArray = {500, 3000, 4000, 7000, 10000, 20000};
for (int size : sizeArray) {
String key = "android_resume_https_v2_" + size + "k";
try {
@@ -275,19 +275,19 @@ public void testHttpsV2(){
}
}
- public void testReuploadV2(){
+ public void testReuploadV2() {
Configuration configuration = new Configuration.Builder()
.resumeUploadVersion(Configuration.RESUME_UPLOAD_VERSION_V2)
.useConcurrentResumeUpload(false)
.useHttps(true)
- .chunkSize(4*1024*1024)
+ .chunkSize(4 * 1024 * 1024)
.build();
int[] sizeArray = {30000};
for (int size : sizeArray) {
String key = "android_resume_reupload_v2_" + size + "k";
try {
File file = TempFile.createFile(size, key);
- reuploadUploadTest((float)0.7, file, key, configuration, null);
+ reuploadUploadTest((long) (size * 0.7), file, key, configuration, null);
TempFile.remove(file);
} catch (IOException e) {
e.printStackTrace();
@@ -295,7 +295,7 @@ public void testReuploadV2(){
}
}
- public void testNoKeyV2(){
+ public void testNoKeyV2() {
int size = 600;
String key = "android_resume_reupload_v2_" + size + "k";
File file = null;
@@ -322,7 +322,7 @@ public void testNoKeyV2(){
TempFile.remove(file);
}
- public void test0kV2(){
+ public void test0kV2() {
int size = 0;
String key = "android_resume_0k_v2_" + size + "k";
File file = null;
@@ -360,12 +360,12 @@ public void testCustomParamV2() {
metaParam.put("x-qn-meta-aaa", "meta_value_1");
metaParam.put("x-qn-meta-key-2", "meta_value_2");
- UploadOptions options = new UploadOptions(userParam, metaParam, null,true, null, null, null);
+ UploadOptions options = new UploadOptions(userParam, metaParam, null, true, null, null, null);
Configuration configuration = new Configuration.Builder()
.resumeUploadVersion(Configuration.RESUME_UPLOAD_VERSION_V2)
.useConcurrentResumeUpload(false)
- .chunkSize(4*1024*1024)
+ .chunkSize(4 * 1024 * 1024)
.useHttps(false)
.build();
diff --git a/library/src/androidTest/java/com/qiniu/android/TempFile.java b/library/src/androidTest/java/com/qiniu/android/TempFile.java
index bb42b331c..03bf95a79 100644
--- a/library/src/androidTest/java/com/qiniu/android/TempFile.java
+++ b/library/src/androidTest/java/com/qiniu/android/TempFile.java
@@ -19,6 +19,7 @@ public static void remove(File f) {
public static File createFile(int kiloSize) throws IOException {
return createFile(kiloSize, "qiniu_" + (1024 * kiloSize) + "k");
}
+
public static File createFile(int kiloSize, String fileName) throws IOException {
FileOutputStream fos = null;
try {
diff --git a/library/src/androidTest/java/com/qiniu/android/TestConfig.java b/library/src/androidTest/java/com/qiniu/android/TestConfig.java
index 1072f6756..9950c6a06 100644
--- a/library/src/androidTest/java/com/qiniu/android/TestConfig.java
+++ b/library/src/androidTest/java/com/qiniu/android/TestConfig.java
@@ -8,22 +8,25 @@
*/
public final class TestConfig {
// TODO: 2020-05-09 bad token for testPutBytesWithFixedZoneUseBackupDomains
- // 华东上传凭证
+// 华东上传凭证
public static final String bucket_z0 = "kodo-phone-zone0-space";
- public static final String token_z0 = "dxVQk8gyk3WswArbNhdKIwmwibJ9nFsQhMNUmtIM:m1kHxpdaFH3NK120iAkHlSwBpio=:eyJzY29wZSI6ImtvZG8tcGhvbmUtem9uZTAtc3BhY2UiLCJkZWFkbGluZSI6MTYxODgxNDM5MCwgInJldHVybkJvZHkiOiJ7XCJjYWxsYmFja1VybFwiOlwiaHR0cDpcL1wvY2FsbGJhY2suZGV2LnFpbml1LmlvXCIsIFwiZm9vXCI6JCh4OmZvbyksIFwiYmFyXCI6JCh4OmJhciksIFwibWltZVR5cGVcIjokKG1pbWVUeXBlKSwgXCJoYXNoXCI6JChldGFnKSwgXCJrZXlcIjokKGtleSksIFwiZm5hbWVcIjokKGZuYW1lKX0ifQ==";
+ public static final String token_z0 = "dxVQk8gyk3WswArbNhdKIwmwibJ9nFsQhMNUmtIM:B6pGDhaMzboJHWnUDi60rrQSB_s=:eyJzY29wZSI6ImtvZG8tcGhvbmUtem9uZTAtc3BhY2UiLCJkZWFkbGluZSI6MTYyNDUwMzMxMywgInJldHVybkJvZHkiOiJ7XCJjYWxsYmFja1VybFwiOlwiaHR0cDpcL1wvY2FsbGJhY2suZGV2LnFpbml1LmlvXCIsIFwiZm9vXCI6JCh4OmZvbyksIFwiYmFyXCI6JCh4OmJhciksIFwibWltZVR5cGVcIjokKG1pbWVUeXBlKSwgXCJoYXNoXCI6JChldGFnKSwgXCJrZXlcIjokKGtleSksIFwiZm5hbWVcIjokKGZuYW1lKX0ifQ==";
// 华北上传凭证
public static final String bucket_z1 = "kodo-phone-zone1-space";
- public static final String token_z1 = "dxVQk8gyk3WswArbNhdKIwmwibJ9nFsQhMNUmtIM:1vkQkb72ANFiAftABJAF2dhbXd0=:eyJzY29wZSI6ImtvZG8tcGhvbmUtem9uZTEtc3BhY2UiLCJkZWFkbGluZSI6MTYxODgxNDM5MCwgInJldHVybkJvZHkiOiJ7XCJjYWxsYmFja1VybFwiOlwiaHR0cDpcL1wvY2FsbGJhY2suZGV2LnFpbml1LmlvXCIsIFwiZm9vXCI6JCh4OmZvbyksIFwiYmFyXCI6JCh4OmJhciksIFwibWltZVR5cGVcIjokKG1pbWVUeXBlKSwgXCJoYXNoXCI6JChldGFnKSwgXCJrZXlcIjokKGtleSksIFwiZm5hbWVcIjokKGZuYW1lKX0ifQ==";
+ public static final String token_z1 = "dxVQk8gyk3WswArbNhdKIwmwibJ9nFsQhMNUmtIM:Oxn6g3rMUNXBoV4yjITYevAj7TI=:eyJzY29wZSI6ImtvZG8tcGhvbmUtem9uZTEtc3BhY2UiLCJkZWFkbGluZSI6MTYyNDUwMzMxMywgInJldHVybkJvZHkiOiJ7XCJjYWxsYmFja1VybFwiOlwiaHR0cDpcL1wvY2FsbGJhY2suZGV2LnFpbml1LmlvXCIsIFwiZm9vXCI6JCh4OmZvbyksIFwiYmFyXCI6JCh4OmJhciksIFwibWltZVR5cGVcIjokKG1pbWVUeXBlKSwgXCJoYXNoXCI6JChldGFnKSwgXCJrZXlcIjokKGtleSksIFwiZm5hbWVcIjokKGZuYW1lKX0ifQ==";
// 华南上传凭证
public static final String bucket_z2 = "kodo-phone-zone2-space";
- public static final String token_z2 = "dxVQk8gyk3WswArbNhdKIwmwibJ9nFsQhMNUmtIM:ZTqDdbvHJuP3hJFckpadCyW08Cs=:eyJzY29wZSI6ImtvZG8tcGhvbmUtem9uZTItc3BhY2UiLCJkZWFkbGluZSI6MTYxODgxNDM5MCwgInJldHVybkJvZHkiOiJ7XCJjYWxsYmFja1VybFwiOlwiaHR0cDpcL1wvY2FsbGJhY2suZGV2LnFpbml1LmlvXCIsIFwiZm9vXCI6JCh4OmZvbyksIFwiYmFyXCI6JCh4OmJhciksIFwibWltZVR5cGVcIjokKG1pbWVUeXBlKSwgXCJoYXNoXCI6JChldGFnKSwgXCJrZXlcIjokKGtleSksIFwiZm5hbWVcIjokKGZuYW1lKX0ifQ==";
+ public static final String token_z2 = "dxVQk8gyk3WswArbNhdKIwmwibJ9nFsQhMNUmtIM:NBqIi2NnZ6ROpSwlAEmsb41Wxec=:eyJzY29wZSI6ImtvZG8tcGhvbmUtem9uZTItc3BhY2UiLCJkZWFkbGluZSI6MTYyNDUwMzMxMywgInJldHVybkJvZHkiOiJ7XCJjYWxsYmFja1VybFwiOlwiaHR0cDpcL1wvY2FsbGJhY2suZGV2LnFpbml1LmlvXCIsIFwiZm9vXCI6JCh4OmZvbyksIFwiYmFyXCI6JCh4OmJhciksIFwibWltZVR5cGVcIjokKG1pbWVUeXBlKSwgXCJoYXNoXCI6JChldGFnKSwgXCJrZXlcIjokKGtleSksIFwiZm5hbWVcIjokKGZuYW1lKX0ifQ==";
// 北美上传凭证
public static final String bucket_na0 = "kodo-phone-zone-na0-space";
- public static final String token_na0 = "dxVQk8gyk3WswArbNhdKIwmwibJ9nFsQhMNUmtIM:I8Q0E32hEelHH4xWBH2p17SxhdA=:eyJzY29wZSI6ImtvZG8tcGhvbmUtem9uZS1uYTAtc3BhY2UiLCJkZWFkbGluZSI6MTYxODgxNDM5MCwgInJldHVybkJvZHkiOiJ7XCJjYWxsYmFja1VybFwiOlwiaHR0cDpcL1wvY2FsbGJhY2suZGV2LnFpbml1LmlvXCIsIFwiZm9vXCI6JCh4OmZvbyksIFwiYmFyXCI6JCh4OmJhciksIFwibWltZVR5cGVcIjokKG1pbWVUeXBlKSwgXCJoYXNoXCI6JChldGFnKSwgXCJrZXlcIjokKGtleSksIFwiZm5hbWVcIjokKGZuYW1lKX0ifQ==";
+ public static final String token_na0 = "dxVQk8gyk3WswArbNhdKIwmwibJ9nFsQhMNUmtIM:CjBzdmymDR-4iQh7GENWdFJnxXc=:eyJzY29wZSI6ImtvZG8tcGhvbmUtem9uZS1uYTAtc3BhY2UiLCJkZWFkbGluZSI6MTYyNDUwMzMxMywgInJldHVybkJvZHkiOiJ7XCJjYWxsYmFja1VybFwiOlwiaHR0cDpcL1wvY2FsbGJhY2suZGV2LnFpbml1LmlvXCIsIFwiZm9vXCI6JCh4OmZvbyksIFwiYmFyXCI6JCh4OmJhciksIFwibWltZVR5cGVcIjokKG1pbWVUeXBlKSwgXCJoYXNoXCI6JChldGFnKSwgXCJrZXlcIjokKGtleSksIFwiZm5hbWVcIjokKGZuYW1lKX0ifQ==";
// 东南亚上传凭证
public static final String bucket_as0 = "kodo-phone-zone-as0-space";
- public static final String token_as0 = "dxVQk8gyk3WswArbNhdKIwmwibJ9nFsQhMNUmtIM:DDXIo7KzUj3ceh5LveRXyNfsiZU=:eyJzY29wZSI6ImtvZG8tcGhvbmUtem9uZS1hczAtc3BhY2UiLCJkZWFkbGluZSI6MTYxODgxNDM5MCwgInJldHVybkJvZHkiOiJ7XCJjYWxsYmFja1VybFwiOlwiaHR0cDpcL1wvY2FsbGJhY2suZGV2LnFpbml1LmlvXCIsIFwiZm9vXCI6JCh4OmZvbyksIFwiYmFyXCI6JCh4OmJhciksIFwibWltZVR5cGVcIjokKG1pbWVUeXBlKSwgXCJoYXNoXCI6JChldGFnKSwgXCJrZXlcIjokKGtleSksIFwiZm5hbWVcIjokKGZuYW1lKX0ifQ==";
- public static final String invalidBucketToken = "dxVQk8gyk3WswArbNhdKIwmwibJ9nFsQhMNUmtIM:Kpi_0B6gZSf7nF5UgdZtvHx0h8M=:eyJzY29wZSI6InpvbmVfaW52YWxpZCIsImRlYWRsaW5lIjoxNjE4ODE0MzkwLCAicmV0dXJuQm9keSI6IntcImNhbGxiYWNrVXJsXCI6XCJodHRwOlwvXC9jYWxsYmFjay5kZXYucWluaXUuaW9cIiwgXCJmb29cIjokKHg6Zm9vKSwgXCJiYXJcIjokKHg6YmFyKSwgXCJtaW1lVHlwZVwiOiQobWltZVR5cGUpLCBcImhhc2hcIjokKGV0YWcpLCBcImtleVwiOiQoa2V5KSwgXCJmbmFtZVwiOiQoZm5hbWUpfSJ9";
+ public static final String token_as0 = "dxVQk8gyk3WswArbNhdKIwmwibJ9nFsQhMNUmtIM:cp_BdEXGx5MieSwlg3kBhl-hfYE=:eyJzY29wZSI6ImtvZG8tcGhvbmUtem9uZS1hczAtc3BhY2UiLCJkZWFkbGluZSI6MTYyNDUwMzMxMywgInJldHVybkJvZHkiOiJ7XCJjYWxsYmFja1VybFwiOlwiaHR0cDpcL1wvY2FsbGJhY2suZGV2LnFpbml1LmlvXCIsIFwiZm9vXCI6JCh4OmZvbyksIFwiYmFyXCI6JCh4OmJhciksIFwibWltZVR5cGVcIjokKG1pbWVUeXBlKSwgXCJoYXNoXCI6JChldGFnKSwgXCJrZXlcIjokKGtleSksIFwiZm5hbWVcIjokKGZuYW1lKX0ifQ==";
+ // 雾存储华东一区
+ public static final String bucket_fog_cn_east1 = "test-fog-cn-east-1";
+ public static final String token_fog_cn_east1 = "dxVQk8gyk3WswArbNhdKIwmwibJ9nFsQhMNUmtIM:iRev7qTeHdPXPURIyVsv2A3qfu0=:eyJzY29wZSI6InRlc3QtZm9nLWNuLWVhc3QtMSIsImRlYWRsaW5lIjoxNjI0NTAzMzEzLCAicmV0dXJuQm9keSI6IntcImNhbGxiYWNrVXJsXCI6XCJodHRwOlwvXC9jYWxsYmFjay5kZXYucWluaXUuaW9cIiwgXCJmb29cIjokKHg6Zm9vKSwgXCJiYXJcIjokKHg6YmFyKSwgXCJtaW1lVHlwZVwiOiQobWltZVR5cGUpLCBcImhhc2hcIjokKGV0YWcpLCBcImtleVwiOiQoa2V5KSwgXCJmbmFtZVwiOiQoZm5hbWUpfSJ9";
+ public static final String invalidBucketToken = "dxVQk8gyk3WswArbNhdKIwmwibJ9nFsQhMNUmtIM:S_IC6jv5EHocYxtU1lrqGcQCUVs=:eyJzY29wZSI6InpvbmVfaW52YWxpZCIsImRlYWRsaW5lIjoxNjI0NTAzMzEzLCAicmV0dXJuQm9keSI6IntcImNhbGxiYWNrVXJsXCI6XCJodHRwOlwvXC9jYWxsYmFjay5kZXYucWluaXUuaW9cIiwgXCJmb29cIjokKHg6Zm9vKSwgXCJiYXJcIjokKHg6YmFyKSwgXCJtaW1lVHlwZVwiOiQobWltZVR5cGUpLCBcImhhc2hcIjokKGV0YWcpLCBcImtleVwiOiQoa2V5KSwgXCJmbmFtZVwiOiQoZm5hbWUpfSJ9";
// -----------
public static final String ak = "bjtWBQXrcxgo7HWwlC_bgHg81j352_GhgBGZPeOW";
diff --git a/library/src/androidTest/java/com/qiniu/android/UploadBaseTest.java b/library/src/androidTest/java/com/qiniu/android/UploadBaseTest.java
index 22a521ca9..437c1db06 100644
--- a/library/src/androidTest/java/com/qiniu/android/UploadBaseTest.java
+++ b/library/src/androidTest/java/com/qiniu/android/UploadBaseTest.java
@@ -1,8 +1,11 @@
package com.qiniu.android;
+import android.net.Uri;
+
import com.qiniu.android.http.ResponseInfo;
import com.qiniu.android.storage.Configuration;
import com.qiniu.android.storage.UpCompletionHandler;
+import com.qiniu.android.storage.UpProgressBytesHandler;
import com.qiniu.android.storage.UpProgressHandler;
import com.qiniu.android.storage.UploadManager;
import com.qiniu.android.storage.UploadOptions;
@@ -12,11 +15,24 @@
import org.json.JSONObject;
import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
import java.io.IOException;
+import java.io.InputStream;
+import java.io.RandomAccessFile;
public class UploadBaseTest extends BaseTest {
- protected UploadOptions defaultOptions = new UploadOptions(null, null, true, new UpProgressHandler() {
+ protected UploadOptions defaultOptions = new UploadOptions(null, null, true, new UpProgressBytesHandler() {
+ @Override
+ public void progress(String key, long uploadBytes, long totalBytes) {
+ double percent = 0;
+ if (totalBytes > 0) {
+ percent = (double) uploadBytes / (double) totalBytes;
+ }
+ LogUtil.d("== upload key:" + (key == null ? "" : key) + " uploadBytes:" + uploadBytes + " totalBytes:" + totalBytes + " percent:" + percent);
+ }
+
@Override
public void progress(String key, double percent) {
LogUtil.d("== upload key:" + (key == null ? "" : key) + " progress:" + percent);
@@ -39,43 +55,27 @@ protected void uploadFileAndAssertSuccessResult(File file,
String key,
Configuration configuration,
UploadOptions options) {
+ uploadFileAndAssertResult(ResponseInfo.RequestSuccess, file, key, configuration, options);
+ }
- final UploadCompleteInfo completeInfo = new UploadCompleteInfo();
- uploadFile(file, key, configuration, options, new UpCompletionHandler() {
- @Override
- public void complete(String key, ResponseInfo info, JSONObject response) {
- completeInfo.responseInfo = info;
- completeInfo.key = key;
- }
- });
-
- wait(new WaitConditional() {
- @Override
- public boolean shouldWait() {
- return completeInfo.responseInfo == null;
- }
- }, 5 * 60);
+ protected void uploadFileAndAssertSuccessResult(UploadInfo file,
+ String key,
+ Configuration configuration,
+ UploadOptions options) {
+ uploadFileAndAssertResult(ResponseInfo.RequestSuccess, file, key, configuration, options);
+ }
- LogUtil.d("=== upload response key:" + (key != null ? key : "") + " response:" + completeInfo.responseInfo);
- assertTrue(completeInfo.responseInfo.toString(), completeInfo.responseInfo != null);
- assertTrue(completeInfo.responseInfo.toString(), completeInfo.responseInfo.isOK());
- assertTrue(completeInfo.responseInfo.toString(), verifyUploadKey(key, completeInfo.key));
+ protected void uploadFileAndAssertResult(int statusCode,
+ File file,
+ String key,
+ Configuration configuration,
+ UploadOptions options) {
- // 成功验证 etag
- String etag = null;
- String serverEtag = null;
- try {
- etag = Etag.file(file);
- serverEtag = completeInfo.responseInfo.response.getString("hash");
- } catch (Exception e) {
- e.printStackTrace();
- }
- LogUtil.d("=== upload etag:" + etag + " response etag:" + serverEtag);
- assertEquals("file:" + etag + " server etag:" + serverEtag, etag, serverEtag);
+ uploadFileAndAssertResult(statusCode, file, TestConfig.token_na0, key, configuration, options);
}
protected void uploadFileAndAssertResult(int statusCode,
- File file,
+ UploadInfo file,
String key,
Configuration configuration,
UploadOptions options) {
@@ -90,121 +90,62 @@ protected void uploadFileAndAssertResult(int statusCode,
Configuration configuration,
UploadOptions options) {
- final UploadCompleteInfo completeInfo = new UploadCompleteInfo();
- uploadFile(file, token, key, configuration, options, new UpCompletionHandler() {
- @Override
- public void complete(String key, ResponseInfo info, JSONObject response) {
- completeInfo.responseInfo = info;
- completeInfo.key = key;
- }
- });
+ UploadInfo fileInfo = new UploadInfo<>(file);
+ fileInfo.configWithFile(file);
+ uploadFileAndAssertResult(statusCode, fileInfo, token, key, configuration, options);
- wait(new WaitConditional() {
- @Override
- public boolean shouldWait() {
- return completeInfo.responseInfo == null;
- }
- }, 5 * 60);
+ Uri uri = Uri.fromFile(file);
+ UploadInfo uriInfo = new UploadInfo<>(uri);
+ uriInfo.configWithFile(file);
+ uploadFileAndAssertResult(statusCode, uriInfo, token, key, configuration, options);
- LogUtil.d("=== upload response key:" + (key != null ? key : "") + " response:" + completeInfo.responseInfo);
- assertTrue(completeInfo.responseInfo.toString(), completeInfo.responseInfo != null);
- assertTrue(completeInfo.responseInfo.toString(), completeInfo.responseInfo.statusCode == statusCode);
- assertTrue(completeInfo.responseInfo.toString(), verifyUploadKey(key, completeInfo.key));
-
- // 成功验证 etag
- if (statusCode == 200) {
- String etag = null;
- String serverEtag = null;
+ InputStream stream = null;
+ try {
+ stream = new FileInputStream(file);
+ } catch (FileNotFoundException e) {
+ }
+ UploadInfo streamInfo = new UploadInfo<>(stream);
+ streamInfo.configWithFile(file);
+ uploadFileAndAssertResult(statusCode, streamInfo, token, key, configuration, options);
+ if (stream != null) {
try {
- etag = Etag.file(file);
- serverEtag = completeInfo.responseInfo.response.getString("hash");
- } catch (Exception e) {
- e.printStackTrace();
+ stream.close();
+ } catch (IOException e) {
}
- LogUtil.d("=== upload etag:" + etag + " response etag:" + serverEtag);
- assertEquals("file:" + etag + " server etag:" + serverEtag, etag, serverEtag);
}
- }
- protected void uploadFile(File file,
- String key,
- Configuration configuration,
- UploadOptions options,
- UpCompletionHandler completionHandler) {
-
- uploadFile(file, TestConfig.token_na0, key, configuration, options, completionHandler);
- }
-
- protected void uploadFile(File file,
- String token,
- String key,
- Configuration configuration,
- UploadOptions options,
- UpCompletionHandler completionHandler) {
- if (options == null) {
- options = defaultOptions;
+ try {
+ stream = new FileInputStream(file);
+ } catch (FileNotFoundException e) {
}
- UploadManager manager = new UploadManager(configuration);
- manager.put(file, key, token, completionHandler, options);
- }
-
-
- protected void uploadDataAndAssertSuccessResult(byte[] data,
- String key,
- Configuration configuration,
- UploadOptions options) {
-
- final UploadCompleteInfo completeInfo = new UploadCompleteInfo();
- uploadData(data, key, configuration, options, new UpCompletionHandler() {
- @Override
- public void complete(String key, ResponseInfo info, JSONObject response) {
- completeInfo.responseInfo = info;
- completeInfo.key = key;
- }
- });
-
- wait(new WaitConditional() {
- @Override
- public boolean shouldWait() {
- return completeInfo.responseInfo == null;
+ streamInfo = new UploadInfo<>(stream);
+ streamInfo.configWithFile(file);
+ streamInfo.size = -1;
+ uploadFileAndAssertResult(statusCode, streamInfo, token, key, configuration, options);
+ if (stream != null) {
+ try {
+ stream.close();
+ } catch (IOException e) {
}
- }, 5 * 60);
-
- LogUtil.d("=== upload response key:" + (key != null ? key : "") + " response:" + completeInfo.responseInfo);
- assertTrue(completeInfo.responseInfo.toString(), completeInfo.responseInfo != null);
- assertTrue(completeInfo.responseInfo.toString(), completeInfo.responseInfo.isOK());
- assertTrue(completeInfo.responseInfo.toString(), verifyUploadKey(key, completeInfo.key));
-
- // 成功验证 etag
- String etag = null;
- String serverEtag = null;
- try {
- etag = Etag.data(data);
- serverEtag = completeInfo.responseInfo.response.getString("hash");
- } catch (Exception e) {
- e.printStackTrace();
}
- LogUtil.d("=== upload etag:" + etag + " response etag:" + serverEtag);
- assertEquals("file:" + etag + " server etag:" + serverEtag, etag, serverEtag);
- }
-
- protected void uploadDataAndAssertResult(int statusCode,
- byte[] data,
- String key,
- Configuration configuration,
- UploadOptions options) {
- uploadDataAndAssertResult(statusCode, data, TestConfig.token_na0, key, configuration, options);
+ if (file.length() < 10 * 1024 * 1024) {
+ byte[] data = getDataFromFile(file);
+ UploadInfo dataInfo = new UploadInfo<>(data);
+ dataInfo.configWithFile(file);
+ uploadFileAndAssertResult(statusCode, dataInfo, token, key, configuration, options);
+ }
}
- protected void uploadDataAndAssertResult(int statusCode,
- byte[] data,
+ protected void uploadFileAndAssertResult(int statusCode,
+ UploadInfo file,
String token,
String key,
Configuration configuration,
UploadOptions options) {
+
final UploadCompleteInfo completeInfo = new UploadCompleteInfo();
- uploadData(data, token, key, configuration, options, new UpCompletionHandler() {
+ upload(file, token, key, configuration, options, new UpCompletionHandler() {
@Override
public void complete(String key, ResponseInfo info, JSONObject response) {
completeInfo.responseInfo = info;
@@ -217,19 +158,18 @@ public void complete(String key, ResponseInfo info, JSONObject response) {
public boolean shouldWait() {
return completeInfo.responseInfo == null;
}
- }, 5 * 60);
+ }, 10 * 60);
- LogUtil.d("=== upload response key:" + (key != null ? key : "") + " response:" + completeInfo.responseInfo);
+ LogUtil.d("=== upload file type:" + file.type() + " response key:" + (key != null ? key : "") + " response:" + completeInfo.responseInfo);
assertTrue(completeInfo.responseInfo.toString(), completeInfo.responseInfo != null);
assertTrue(completeInfo.responseInfo.toString(), completeInfo.responseInfo.statusCode == statusCode);
assertTrue(completeInfo.responseInfo.toString(), verifyUploadKey(key, completeInfo.key));
// 成功验证 etag
- if (statusCode == 200) {
- String etag = null;
+ if (statusCode == ResponseInfo.RequestSuccess) {
+ String etag = file.etag;
String serverEtag = null;
try {
- etag = Etag.data(data);
serverEtag = completeInfo.responseInfo.response.getString("hash");
} catch (Exception e) {
e.printStackTrace();
@@ -239,28 +179,88 @@ public boolean shouldWait() {
}
}
- protected void uploadData(byte[] data,
- String key,
- Configuration configuration,
- UploadOptions options,
- UpCompletionHandler completionHandler) {
+ protected void upload(UploadInfo file,
+ String key,
+ Configuration configuration,
+ UploadOptions options,
+ UpCompletionHandler completionHandler) {
- uploadData(data, TestConfig.token_na0, key, configuration, options, completionHandler);
+ upload(file, TestConfig.token_na0, key, configuration, options, completionHandler);
}
- protected void uploadData(byte[] data,
- String token,
- String key,
- Configuration configuration,
- UploadOptions options,
- UpCompletionHandler completionHandler) {
+ protected void upload(UploadInfo file,
+ String token,
+ String key,
+ Configuration configuration,
+ UploadOptions options,
+ UpCompletionHandler completionHandler) {
if (options == null) {
options = defaultOptions;
}
UploadManager manager = new UploadManager(configuration);
- manager.put(data, key, token, completionHandler, options);
+ if (file.info instanceof File) {
+ manager.put((File) file.info, key, token, completionHandler, options);
+ } else if (file.info instanceof Uri) {
+ manager.put((Uri) file.info, null, key, token, completionHandler, options);
+ } else if (file.info instanceof InputStream) {
+ manager.put((InputStream) file.info, null, file.size, file.fileName, key, token, completionHandler, options);
+ } else if (file.info instanceof byte[]) {
+ manager.put((byte[]) file.info, key, token, completionHandler, options);
+ } else {
+ completionHandler.complete(key, ResponseInfo.fileError(new Exception("test case file type error")), null);
+ }
+ }
+
+ protected byte[] getDataFromFile(File file) {
+ byte[] bytes = new byte[(int) file.length()];
+ try {
+ RandomAccessFile accessFile = new RandomAccessFile(file, "r");
+ accessFile.readFully(bytes);
+ } catch (Exception e) {
+ bytes = null;
+ }
+ return bytes;
}
+ protected static class UploadInfo {
+ protected final T info;
+ protected String fileName;
+ protected long size = -1;
+ protected String etag;
+ protected String md5;
+
+ public UploadInfo(T info) {
+ this.info = info;
+ }
+
+ public void configWithFile(File file) {
+ fileName = file.getName();
+ size = file.length();
+ try {
+ etag = Etag.file(file);
+ } catch (Exception ignore) {
+ }
+
+ try {
+ etag = Etag.file(file);
+ } catch (Exception ignore) {
+ }
+ }
+
+ public String type() {
+ if (info instanceof File) {
+ return "file";
+ } else if (info instanceof Uri) {
+ return "uri";
+ } else if (info instanceof InputStream) {
+ return "stream";
+ } else if (info instanceof byte[]) {
+ return "byte_array";
+ } else {
+ return "none";
+ }
+ }
+ }
protected static class UploadCompleteInfo {
String key;
diff --git a/library/src/androidTest/java/com/qiniu/android/UploadFlowTest.java b/library/src/androidTest/java/com/qiniu/android/UploadFlowTest.java
index a7e062db3..7170213d2 100644
--- a/library/src/androidTest/java/com/qiniu/android/UploadFlowTest.java
+++ b/library/src/androidTest/java/com/qiniu/android/UploadFlowTest.java
@@ -1,5 +1,7 @@
package com.qiniu.android;
+import android.net.Uri;
+
import com.qiniu.android.common.FixedZone;
import com.qiniu.android.common.ZoneInfo;
import com.qiniu.android.common.ZonesInfo;
@@ -8,6 +10,7 @@
import com.qiniu.android.storage.FileRecorder;
import com.qiniu.android.storage.UpCancellationSignal;
import com.qiniu.android.storage.UpCompletionHandler;
+import com.qiniu.android.storage.UpProgressBytesHandler;
import com.qiniu.android.storage.UpProgressHandler;
import com.qiniu.android.storage.UploadOptions;
import com.qiniu.android.utils.LogUtil;
@@ -16,66 +19,66 @@
import org.json.JSONObject;
import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
import java.io.IOException;
+import java.io.InputStream;
import java.util.ArrayList;
public class UploadFlowTest extends UploadBaseTest {
- protected void cancelTest(final float cancelPercent,
+ protected void cancelTest(long cancelPosition,
File file,
String key,
Configuration configuration,
UploadOptions options) {
+ cancelPosition *= 1024;
- if (options == null) {
- options = defaultOptions;
- }
-
- final UploadOptions optionsReal = options;
- final Flags flags = new Flags();
- UploadOptions cancelOptions = new UploadOptions(optionsReal.params, optionsReal.mimeType, optionsReal.checkCrc, new UpProgressHandler() {
- @Override
- public void progress(String key, double percent) {
- if (cancelPercent <= percent) {
- flags.shouldCancel = true;
- }
- if (optionsReal.progressHandler != null) {
- optionsReal.progressHandler.progress(key, percent);
- }
- }
- }, new UpCancellationSignal() {
- @Override
- public boolean isCancelled() {
+ LogUtil.d("======== progress File cancel ============================================");
+ UploadInfo fileInfo = new UploadInfo<>(file);
+ fileInfo.configWithFile(file);
+ cancelTest(cancelPosition, fileInfo, key, configuration, options);
- return flags.shouldCancel;
- }
- }, options.netReadyHandler);
+ Uri uri = Uri.fromFile(file);
+ UploadInfo uriInfo = new UploadInfo<>(uri);
+ uriInfo.configWithFile(file);
+ cancelTest(cancelPosition, uriInfo, key, configuration, options);
- final UploadCompleteInfo completeInfo = new UploadCompleteInfo();
- uploadFile(file, key, configuration, cancelOptions, new UpCompletionHandler() {
- @Override
- public void complete(String key, ResponseInfo info, JSONObject response) {
- completeInfo.key = key;
- completeInfo.responseInfo = info;
- }
- });
+ LogUtil.d("======== progress InputStream with size cancel ===========================");
+ InputStream stream = null;
+ try {
+ stream = new FileInputStream(file);
+ } catch (FileNotFoundException e) {
+ }
+ UploadInfo streamInfo = new UploadInfo<>(stream);
+ streamInfo.configWithFile(file);
+ cancelTest(cancelPosition, streamInfo, key, configuration, options);
- wait(new WaitConditional() {
- @Override
- public boolean shouldWait() {
- return completeInfo.responseInfo == null;
- }
- }, 5 * 60);
- assertTrue(completeInfo.responseInfo.toString(), completeInfo.responseInfo != null);
- assertTrue(completeInfo.responseInfo.toString(), completeInfo.responseInfo.isCancelled());
- assertTrue(completeInfo.responseInfo.toString(), verifyUploadKey(key, completeInfo.key));
+ LogUtil.d("======== progress InputStream without size cancel =========================");
+ stream = null;
+ try {
+ stream = new FileInputStream(file);
+ } catch (FileNotFoundException e) {
+ }
+ streamInfo = new UploadInfo<>(stream);
+ streamInfo.configWithFile(file);
+ streamInfo.size = -1;
+ cancelTest(cancelPosition, streamInfo, key, configuration, options);
+
+ LogUtil.d("======== progress data cancel =============================================");
+ if (file.length() < 10 * 1024 * 1024) {
+ byte[] data = getDataFromFile(file);
+ UploadInfo dataInfo = new UploadInfo<>(data);
+ dataInfo.configWithFile(file);
+ cancelTest(cancelPosition, dataInfo, key, configuration, options);
+ }
}
- protected void cancelTest(final float cancelPercent,
- byte[] data,
- String key,
- Configuration configuration,
- UploadOptions options) {
+ private void cancelTest(final long cancelPosition,
+ UploadInfo file,
+ String key,
+ Configuration configuration,
+ UploadOptions options) {
if (options == null) {
options = defaultOptions;
@@ -83,16 +86,20 @@ protected void cancelTest(final float cancelPercent,
final UploadOptions optionsReal = options;
final Flags flags = new Flags();
- UploadOptions cancelOptions = new UploadOptions(optionsReal.params, optionsReal.mimeType, optionsReal.checkCrc, new UpProgressHandler() {
+ UploadOptions cancelOptions = new UploadOptions(optionsReal.params, optionsReal.mimeType, optionsReal.checkCrc, new UpProgressBytesHandler() {
@Override
- public void progress(String key, double percent) {
- if (cancelPercent <= percent) {
+ public void progress(String key, long uploadBytes, long totalBytes) {
+ if (cancelPosition < uploadBytes) {
flags.shouldCancel = true;
}
- if (optionsReal.progressHandler != null) {
- optionsReal.progressHandler.progress(key, percent);
+ if (optionsReal.progressHandler instanceof UpProgressBytesHandler) {
+ ((UpProgressBytesHandler)optionsReal.progressHandler).progress(key, uploadBytes, totalBytes);
}
}
+
+ @Override
+ public void progress(String key, double percent) {
+ }
}, new UpCancellationSignal() {
@Override
public boolean isCancelled() {
@@ -102,7 +109,7 @@ public boolean isCancelled() {
}, options.netReadyHandler);
final UploadCompleteInfo completeInfo = new UploadCompleteInfo();
- uploadData(data, key, configuration, cancelOptions, new UpCompletionHandler() {
+ upload(file, key, configuration, cancelOptions, new UpCompletionHandler() {
@Override
public void complete(String key, ResponseInfo info, JSONObject response) {
completeInfo.key = key;
@@ -121,105 +128,83 @@ public boolean shouldWait() {
assertTrue(completeInfo.responseInfo.toString(), verifyUploadKey(key, completeInfo.key));
}
-
- protected void reuploadUploadTest(final float resumePercent,
- final File file,
+ protected void reuploadUploadTest(long resumePosition,
+ File file,
String key,
- final Configuration configuration,
+ Configuration configuration,
UploadOptions options) {
- FileRecorder fileRecorder = null;
- try {
- fileRecorder = new FileRecorder(Utils.sdkDirectory() + "/Test");
- } catch (IOException e) {
- e.printStackTrace();
- }
+ resumePosition *= 1024;
- final Configuration reuploadConfiguration = new Configuration.Builder()
- .chunkSize(configuration.chunkSize)
- .putThreshold(configuration.putThreshold)
- .retryMax(configuration.retryMax)
- .connectTimeout(configuration.connectTimeout)
- .responseTimeout(configuration.responseTimeout)
- .retryInterval(configuration.retryInterval)
- .recorder(fileRecorder, null)
- .proxy(configuration.proxy)
- .urlConverter(configuration.urlConverter)
- .useHttps(configuration.useHttps)
- .allowBackupHost(configuration.allowBackupHost)
- .useConcurrentResumeUpload(configuration.useConcurrentResumeUpload)
- .resumeUploadVersion(configuration.resumeUploadVersion)
- .concurrentTaskCount(configuration.concurrentTaskCount)
- .zone(configuration.zone)
- .build();
+ LogUtil.d("======== progress File ReUpload ==============================================");
+ UploadInfo fileInfo = new UploadInfo<>(file);
+ fileInfo.configWithFile(file);
+ reuploadUploadTest(resumePosition, fileInfo, fileInfo, key, configuration, options);
+ LogUtil.d("======== progress Uri ReUpload ==============================================");
+ Uri uri = Uri.fromFile(file);
+ UploadInfo uriInfo = new UploadInfo<>(uri);
+ uriInfo.configWithFile(file);
+ reuploadUploadTest(resumePosition, uriInfo, uriInfo, key, configuration, options);
- if (options == null) {
- options = defaultOptions;
+ LogUtil.d("======== progress InputStream with size ReUpload =============================");
+ InputStream firstStream = null;
+ try {
+ firstStream = new FileInputStream(file);
+ } catch (FileNotFoundException e) {
}
- final UploadOptions optionsReal = options;
-
- cancelTest(resumePercent, file, key, reuploadConfiguration, optionsReal);
+ UploadInfo firstStreamInfo = new UploadInfo<>(firstStream);
+ firstStreamInfo.configWithFile(file);
+ InputStream secondStream = null;
+ try {
+ secondStream = new FileInputStream(file);
+ } catch (FileNotFoundException e) {
+ }
+ UploadInfo secondStreamInfo = new UploadInfo<>(secondStream);
+ secondStreamInfo.configWithFile(file);
- final Flags flags = new Flags();
- UploadOptions reuploadOptions = new UploadOptions(optionsReal.params, optionsReal.mimeType, optionsReal.checkCrc, new UpProgressHandler() {
- @Override
- public void progress(String key, double percent) {
- if (!flags.flags) {
- flags.flags = true;
- double minPercent = 0;
- double currentChunkCount = 0;
- double chunkSize = 0;
- if (!reuploadConfiguration.useConcurrentResumeUpload) {
- currentChunkCount = 1;
- chunkSize = reuploadConfiguration.chunkSize;
- } else if (reuploadConfiguration.resumeUploadVersion == Configuration.RESUME_UPLOAD_VERSION_V1) {
- currentChunkCount = reuploadConfiguration.concurrentTaskCount;
- chunkSize = Configuration.BLOCK_SIZE;
- } else {
- currentChunkCount = reuploadConfiguration.concurrentTaskCount;
- chunkSize = reuploadConfiguration.chunkSize;
- }
- minPercent = percent + currentChunkCount * chunkSize / (double) file.length();
- if (resumePercent <= minPercent) {
- flags.isSuccess = true;
- }
- LogUtil.d("== upload reupload percent:" + percent + " minPercent:" + minPercent);
- }
+ reuploadUploadTest(resumePosition, firstStreamInfo, secondStreamInfo, key, configuration, options);
+ try {
+ firstStream.close();
+ secondStream.close();
+ } catch (IOException e) {
+ }
- if (optionsReal.progressHandler != null) {
- optionsReal.progressHandler.progress(key, percent);
- }
- }
- }, null, options.netReadyHandler);
+ LogUtil.d("======== progress InputStream without size ReUpload ==========================");
+ firstStream = null;
+ try {
+ firstStream = new FileInputStream(file);
+ } catch (FileNotFoundException e) {
+ }
+ firstStreamInfo = new UploadInfo<>(firstStream);
+ firstStreamInfo.configWithFile(file);
+ firstStreamInfo.size = -1;
- final UploadCompleteInfo completeInfo = new UploadCompleteInfo();
- uploadFile(file, key, reuploadConfiguration, reuploadOptions, new UpCompletionHandler() {
- @Override
- public void complete(String key, ResponseInfo info, JSONObject response) {
- completeInfo.key = key;
- completeInfo.responseInfo = info;
- }
- });
+ secondStream = null;
+ try {
+ secondStream = new FileInputStream(file);
+ } catch (FileNotFoundException e) {
+ }
+ secondStreamInfo = new UploadInfo<>(secondStream);
+ secondStreamInfo.configWithFile(file);
+ secondStreamInfo.size = -1;
- wait(new WaitConditional() {
- @Override
- public boolean shouldWait() {
- return completeInfo.responseInfo == null;
- }
- }, 5 * 60);
- assertTrue(completeInfo.responseInfo.toString(), flags.isSuccess);
- assertTrue(completeInfo.responseInfo.toString(), completeInfo.responseInfo != null);
- assertTrue(completeInfo.responseInfo.toString(), completeInfo.responseInfo.isOK());
- assertTrue(completeInfo.responseInfo.toString(), verifyUploadKey(key, completeInfo.key));
+ reuploadUploadTest(resumePosition, firstStreamInfo, secondStreamInfo, key, configuration, options);
+ try {
+ firstStream.close();
+ secondStream.close();
+ } catch (IOException e) {
+ }
}
- protected void reuploadUploadTest(final float reuploadPercent,
- final byte[] data,
- String key,
- final Configuration configuration,
- UploadOptions options) {
+ private void reuploadUploadTest(final long resumePosition,
+ final UploadInfo firstFile,
+ final UploadInfo secondFile,
+ String key,
+ final Configuration configuration,
+ UploadOptions options) {
+
FileRecorder fileRecorder = null;
try {
fileRecorder = new FileRecorder(Utils.sdkDirectory() + "/Test");
@@ -244,45 +229,40 @@ protected void reuploadUploadTest(final float reuploadPercent,
.concurrentTaskCount(configuration.concurrentTaskCount)
.zone(configuration.zone)
.build();
+
+
if (options == null) {
options = defaultOptions;
}
final UploadOptions optionsReal = options;
- cancelTest(reuploadPercent, data, key, reuploadConfiguration, optionsReal);
+ cancelTest(resumePosition, firstFile, key, reuploadConfiguration, optionsReal);
+
+ LogUtil.d("progress ReUpload ====================================================");
final Flags flags = new Flags();
- UploadOptions reuploadOptions = new UploadOptions(optionsReal.params, optionsReal.mimeType, optionsReal.checkCrc, new UpProgressHandler() {
+ UploadOptions reuploadOptions = new UploadOptions(optionsReal.params, optionsReal.mimeType, optionsReal.checkCrc, new UpProgressBytesHandler() {
@Override
public void progress(String key, double percent) {
+ }
+
+ @Override
+ public void progress(String key, long uploadBytes, long totalBytes) {
if (!flags.flags) {
- double minPercent = 0;
- double currentChunkCount = 0;
- double chunkSize = 0;
- if (!reuploadConfiguration.useConcurrentResumeUpload) {
- currentChunkCount = 1;
- chunkSize = reuploadConfiguration.chunkSize;
- } else if (reuploadConfiguration.resumeUploadVersion == Configuration.RESUME_UPLOAD_VERSION_V1) {
- currentChunkCount = reuploadConfiguration.concurrentTaskCount;
- chunkSize = Configuration.BLOCK_SIZE;
- } else {
- currentChunkCount = reuploadConfiguration.concurrentTaskCount;
- chunkSize = reuploadConfiguration.chunkSize;
- }
- minPercent = percent + currentChunkCount * chunkSize / (double) data.length;
- if (reuploadPercent >= minPercent) {
+ flags.flags = true;
+ if (uploadBytes <= resumePosition && uploadBytes > 0) {
flags.isSuccess = true;
}
- LogUtil.d("== reupload percent:" + percent + " minPercent:" + minPercent);
}
- if (optionsReal.progressHandler != null) {
- optionsReal.progressHandler.progress(key, percent);
+
+ if (optionsReal.progressHandler != null && optionsReal.progressHandler instanceof UpProgressBytesHandler) {
+ ((UpProgressBytesHandler)optionsReal.progressHandler).progress(key, uploadBytes, totalBytes);
}
}
}, null, options.netReadyHandler);
final UploadCompleteInfo completeInfo = new UploadCompleteInfo();
- uploadData(data, key, reuploadConfiguration, reuploadOptions, new UpCompletionHandler() {
+ upload(secondFile, key, reuploadConfiguration, reuploadOptions, new UpCompletionHandler() {
@Override
public void complete(String key, ResponseInfo info, JSONObject response) {
completeInfo.key = key;
@@ -295,8 +275,7 @@ public void complete(String key, ResponseInfo info, JSONObject response) {
public boolean shouldWait() {
return completeInfo.responseInfo == null;
}
- }, 5 * 60);
-
+ }, 10* 60);
assertTrue(completeInfo.responseInfo.toString(), flags.isSuccess);
assertTrue(completeInfo.responseInfo.toString(), completeInfo.responseInfo != null);
assertTrue(completeInfo.responseInfo.toString(), completeInfo.responseInfo.isOK());
@@ -307,50 +286,26 @@ protected void switchRegionTestWithFile(File file,
String key,
Configuration configuration,
UploadOptions options) {
- if (configuration == null) {
- configuration = new Configuration.Builder().build();
- }
- Configuration configurationReal = configuration;
- ArrayList hostArray0 = new ArrayList<>();
- hostArray0.add("mock1.up.qiniup.com");
- hostArray0.add("mock2.up.qiniup.com");
- ZoneInfo zoneInfo0 = ZoneInfo.buildInfo(hostArray0, null, null);
- ArrayList hostArray1 = new ArrayList<>();
- hostArray1.add("upload-na0.qiniup.com");
- hostArray1.add("up-na0.qiniup.com");
- ZoneInfo zoneInfo1 = ZoneInfo.buildInfo(hostArray1, null, null);
+ UploadInfo fileInfo = new UploadInfo<>(file);
+ fileInfo.configWithFile(file);
+ switchRegionTestWithFile(fileInfo, key, configuration, options);
- ArrayList zoneInfoArray = new ArrayList<>();
- zoneInfoArray.add(zoneInfo0);
- zoneInfoArray.add(zoneInfo1);
- ZonesInfo zonesInfo = new ZonesInfo(zoneInfoArray);
- FixedZone zone = new FixedZone(zonesInfo);
+ Uri uri = Uri.fromFile(file);
+ UploadInfo uriInfo = new UploadInfo<>(uri);
+ uriInfo.configWithFile(file);
+ switchRegionTestWithFile(uriInfo, key, configuration, options);
- Configuration switchConfiguration = new Configuration.Builder()
- .chunkSize(configurationReal.chunkSize)
- .putThreshold(configurationReal.putThreshold)
- .retryMax(configurationReal.retryMax)
- .connectTimeout(configurationReal.connectTimeout)
- .responseTimeout(configurationReal.responseTimeout)
- .retryInterval(configurationReal.retryInterval)
- .recorder(configurationReal.recorder, configurationReal.keyGen)
- .proxy(configurationReal.proxy)
- .urlConverter(configurationReal.urlConverter)
- .useHttps(configurationReal.useHttps)
- .allowBackupHost(configurationReal.allowBackupHost)
- .useConcurrentResumeUpload(configurationReal.useConcurrentResumeUpload)
- .resumeUploadVersion(configurationReal.resumeUploadVersion)
- .concurrentTaskCount(configurationReal.concurrentTaskCount)
- .zone(zone)
- .build();
- uploadFileAndAssertSuccessResult(file, key, switchConfiguration, options);
+ byte[] data = getDataFromFile(file);
+ UploadInfo dataInfo = new UploadInfo<>(data);
+ dataInfo.configWithFile(file);
+ switchRegionTestWithFile(dataInfo, key, configuration, options);
}
- protected void switchRegionTestWithData(byte[] data,
- String key,
- Configuration configuration,
- UploadOptions options) {
+ private void switchRegionTestWithFile(UploadInfo file,
+ String key,
+ Configuration configuration,
+ UploadOptions options) {
if (configuration == null) {
configuration = new Configuration.Builder().build();
}
@@ -386,11 +341,11 @@ protected void switchRegionTestWithData(byte[] data,
.useConcurrentResumeUpload(configurationReal.useConcurrentResumeUpload)
.resumeUploadVersion(configurationReal.resumeUploadVersion)
.concurrentTaskCount(configurationReal.concurrentTaskCount)
+ .zone(zone)
.build();
- uploadDataAndAssertSuccessResult(data, key, switchConfiguration, options);
+ uploadFileAndAssertSuccessResult(file, key, switchConfiguration, options);
}
-
protected static class Flags {
boolean flags;
boolean shouldCancel;
diff --git a/library/src/androidTest/java/com/qiniu/android/UriTest.java b/library/src/androidTest/java/com/qiniu/android/UriTest.java
new file mode 100644
index 000000000..32cf77f42
--- /dev/null
+++ b/library/src/androidTest/java/com/qiniu/android/UriTest.java
@@ -0,0 +1,190 @@
+package com.qiniu.android;
+
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.net.Uri;
+import android.provider.MediaStore;
+
+import com.qiniu.android.http.ResponseInfo;
+import com.qiniu.android.storage.Configuration;
+import com.qiniu.android.storage.UpCompletionHandler;
+import com.qiniu.android.storage.UploadManager;
+import com.qiniu.android.utils.ContextGetter;
+import com.qiniu.android.utils.Etag;
+import com.qiniu.android.utils.LogUtil;
+
+import junit.framework.Assert;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+public class UriTest extends BaseTest {
+
+ private static boolean[][] testConfigList = {
+ {true, true, true},
+ {true, true, false},
+ {true, false, true},
+ {true, false, false},
+
+ {false, true, true},
+ {false, true, false},
+ {false, false, true},
+ {false, false, false},
+ };
+
+ public void notestUpload() {
+ int MB = 1024;
+ int[] sizeList = {512, MB, 4*MB, 5*MB, 8*MB, 10*MB, 20*MB};
+ for (int size : sizeList) {
+ String fileName = size + "KB" + ".mp4";
+
+ File file = createFile(size);
+ Uri uri = null;
+ try {
+ uri = writeFileToDownload(file, fileName);
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ Assert.fail(e.getMessage());
+ return;
+ }
+
+ String etag = null;
+ try {
+ etag = Etag.file(file);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ for (boolean[] config : testConfigList) {
+ testUpload(uri, fileName, etag, config[0], config[1], config[2]);
+ }
+ removeUri(uri);
+ }
+ }
+
+ private void testUpload(Uri uri, String fileName, String etag, boolean isHttps, boolean isResumableV1, boolean isConcurrent) {
+
+ assertNotNull("Uri write file error:" + fileName, uri);
+
+ Configuration configuration = new Configuration.Builder()
+ .resumeUploadVersion(isResumableV1 ? Configuration.RESUME_UPLOAD_VERSION_V1 : Configuration.RESUME_UPLOAD_VERSION_V2)
+ .chunkSize(isResumableV1 ? 1024*1024*2 : 1024*1024*4)
+ .useConcurrentResumeUpload(isConcurrent)
+ .useHttps(isHttps)
+ .build();
+
+ UploadManager uploadManager = new UploadManager(configuration);
+
+ String key = "uri_upload_";
+ key += isHttps ? "https_" : "http_";
+ key += isResumableV1 ? "v1_" : "v2_";
+ key += isConcurrent ? "serial_" : "concurrent_";
+ key += fileName;
+ final UploadCompleteInfo completeInfo = new UploadCompleteInfo();
+ uploadManager.put(uri, null, key, TestConfig.token_na0, new UpCompletionHandler() {
+ @Override
+ public void complete(String key, ResponseInfo info, JSONObject response) {
+ completeInfo.key = key;
+ completeInfo.responseInfo = info;
+ }
+ }, null);
+
+ wait(new WaitConditional() {
+ @Override
+ public boolean shouldWait() {
+ return completeInfo.responseInfo == null;
+ }
+ }, 10 * 60);
+
+ LogUtil.d("=== upload response key:" + (key != null ? key : "") + " response:" + completeInfo.responseInfo);
+ assertTrue(completeInfo.responseInfo.toString(), completeInfo.responseInfo != null);
+ assertTrue(completeInfo.responseInfo.toString(), completeInfo.responseInfo.statusCode == ResponseInfo.RequestSuccess);
+ assertTrue(completeInfo.responseInfo.toString(), key.equals(completeInfo.key));
+
+ String serverEtag = null;
+ try {
+ serverEtag = completeInfo.responseInfo.response.getString("hash");
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ System.out.println(" etag:" + etag);
+ System.out.println("serverEtag:" + serverEtag);
+ assertNotNull("key:" + key, serverEtag);
+ assertEquals("key:" + key, etag, serverEtag);
+ }
+
+ private File createFile(int size) {
+ File file = null;
+ try {
+ file = TempFile.createFile(size);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return file;
+ }
+
+ private Uri writeFileToDownload(File file, String fileName) throws FileNotFoundException {
+
+ InputStream inputStream = null;
+ try {
+ inputStream = new FileInputStream(file);
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ throw e;
+ }
+
+ ContentResolver resolver = ContextGetter.applicationContext().getContentResolver();
+
+ ContentValues contentValues = new ContentValues();
+ contentValues.put(MediaStore.Video.Media.DISPLAY_NAME, fileName);
+ Uri imageUri = null;
+ try {
+ imageUri = resolver.insert(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, contentValues);
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw e;
+ }
+
+ if (imageUri != null) {
+ // 若生成了uri,则表示该文件添加成功
+ // 使用流将内容写入该uri中即可
+ OutputStream outputStream = null;
+ try {
+ outputStream = resolver.openOutputStream(imageUri);
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ }
+ if (outputStream != null) {
+ try {
+ byte[] buf = new byte[1024];
+ int len;
+ while ((len = inputStream.read(buf)) > 0) {
+ outputStream.write(buf, 0, len);
+ }
+ outputStream.close();
+ inputStream.close();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ return imageUri;
+ }
+
+ private void removeUri(Uri uri) {
+ ContentResolver resolver = ContextGetter.applicationContext().getContentResolver();
+ resolver.delete(uri, null, null);
+ }
+
+ protected static class UploadCompleteInfo {
+ String key;
+ ResponseInfo responseInfo;
+ }
+}
diff --git a/library/src/androidTest/java/com/qiniu/android/UtilsTest.java b/library/src/androidTest/java/com/qiniu/android/UtilsTest.java
index 9eb9391c5..3770af187 100644
--- a/library/src/androidTest/java/com/qiniu/android/UtilsTest.java
+++ b/library/src/androidTest/java/com/qiniu/android/UtilsTest.java
@@ -27,4 +27,46 @@ public void testIPType(){
type = Utils.getIpType("2000::0001:2345:6789:abcd", testHost);
assertTrue(type.equals(testHost + "-ipv6-2000-0000-0000-0000"));
}
+
+ public void testIsIPType(){
+
+ String ip = null;
+ boolean isIpv6 = false;
+
+ ip = "10.10.120.3";
+ isIpv6 = Utils.isIpv6(ip);
+ assertFalse(ip, isIpv6);
+
+ ip = "130.101.120.3";
+ isIpv6 = Utils.isIpv6(ip);
+ assertFalse(ip, isIpv6);
+
+ ip = "2000:0000:0000:0000:0001:2345:6789:abcd";
+ isIpv6 = Utils.isIpv6(ip);
+ assertTrue(ip, isIpv6);
+
+ ip = "2000:0:0:0:0001:2345:6789:abcd";
+ isIpv6 = Utils.isIpv6(ip);
+ assertTrue(ip, isIpv6);
+
+ ip = "2000::0001:2345:6789:abcd";
+ isIpv6 = Utils.isIpv6(ip);
+ assertTrue(ip, isIpv6);
+
+ ip = "0::0";
+ isIpv6 = Utils.isIpv6(ip);
+ assertTrue(ip, isIpv6);
+
+ ip = "ffff::ffff:2345:6789:abcd";
+ isIpv6 = Utils.isIpv6(ip);
+ assertTrue(ip, isIpv6);
+
+ ip = "ff1::ffff:2345:6789:abcd";
+ isIpv6 = Utils.isIpv6(ip);
+ assertTrue(ip, isIpv6);
+
+ ip = "ffff1::ffff:2345:6789:abcd";
+ isIpv6 = Utils.isIpv6(ip);
+ assertFalse(ip, isIpv6);
+ }
}
diff --git a/library/src/main/java/com/qiniu/android/common/Constants.java b/library/src/main/java/com/qiniu/android/common/Constants.java
index 91e6c4b65..14a3e01d6 100644
--- a/library/src/main/java/com/qiniu/android/common/Constants.java
+++ b/library/src/main/java/com/qiniu/android/common/Constants.java
@@ -2,7 +2,7 @@
public final class Constants {
- public static final String VERSION = "8.2.1";
+ public static final String VERSION = "8.3.0";
public static final String UTF_8 = "utf-8";
}
diff --git a/library/src/main/java/com/qiniu/android/common/ZoneInfo.java b/library/src/main/java/com/qiniu/android/common/ZoneInfo.java
index b6a880368..1df62b8ab 100644
--- a/library/src/main/java/com/qiniu/android/common/ZoneInfo.java
+++ b/library/src/main/java/com/qiniu/android/common/ZoneInfo.java
@@ -25,6 +25,7 @@ public class ZoneInfo {
public final int ttl;
public final boolean http3Enabled;
+ public final boolean ipv6;
public final List domains;
public final List old_domains;
@@ -72,11 +73,13 @@ public static ZoneInfo buildInfo(List mainHosts,
private ZoneInfo(int ttl,
boolean http3Enabled,
+ boolean ipv6,
String regionId,
List domains,
List old_domains) {
this.ttl = ttl;
this.http3Enabled = http3Enabled;
+ this.ipv6 = ipv6;
this.regionId = regionId;
this.domains = domains;
this.old_domains = old_domains;
@@ -95,18 +98,22 @@ public static ZoneInfo buildFromJson(JSONObject obj) throws JSONException {
int ttl = obj.optInt("ttl");
boolean http3Enabled = false;
+ boolean ipv6Enabled = false;
try {
JSONObject features = obj.getJSONObject("features");
- JSONObject http3 = features.getJSONObject("http3");
- http3Enabled = http3.getBoolean("enabled");
- } catch (Exception ignored) {
- }
+ JSONObject http3 = features.optJSONObject("http3");
+ if (http3 != null) {
+ http3Enabled = http3.optBoolean("enabled");
+ }
- String regionId = obj.optString("region");
- if (regionId == null) {
- regionId = EmptyRegionId;
+ JSONObject ipv6 = features.optJSONObject("ipv6");
+ if (ipv6 != null) {
+ ipv6Enabled = ipv6.optBoolean("enabled");
+ }
+ } catch (Exception ignored) {
}
+ String regionId = obj.optString("region", EmptyRegionId);
JSONObject up = obj.optJSONObject("up");
if (up == null) {
return null;
@@ -141,7 +148,7 @@ public static ZoneInfo buildFromJson(JSONObject obj) throws JSONException {
return null;
}
- ZoneInfo zoneInfo = new ZoneInfo(ttl, http3Enabled, regionId, domains, old_domains);
+ ZoneInfo zoneInfo = new ZoneInfo(ttl, http3Enabled, ipv6Enabled, regionId, domains, old_domains);
zoneInfo.detailInfo = obj;
zoneInfo.allHosts = allHosts;
@@ -167,6 +174,7 @@ public boolean isValid() {
return ttl > (currentTimestamp - buildTimestamp);
}
+ @Deprecated
public static class UploadServerGroup {
public final String info;
public final ArrayList main;
diff --git a/library/src/main/java/com/qiniu/android/http/request/httpclient/ByteBody.java b/library/src/main/java/com/qiniu/android/http/request/httpclient/ByteBody.java
index da5604fa1..a136b5006 100644
--- a/library/src/main/java/com/qiniu/android/http/request/httpclient/ByteBody.java
+++ b/library/src/main/java/com/qiniu/android/http/request/httpclient/ByteBody.java
@@ -1,11 +1,15 @@
package com.qiniu.android.http.request.httpclient;
+import java.io.ByteArrayInputStream;
import java.io.IOException;
+import java.io.InputStream;
import java.util.Arrays;
import okhttp3.MediaType;
import okhttp3.RequestBody;
import okio.BufferedSink;
+import okio.Okio;
+import okio.Source;
/**
* Created by yangsen on 2020/6/10
@@ -37,23 +41,21 @@ public long contentLength() throws IOException {
@Override
public void writeTo(BufferedSink bufferedSink) throws IOException {
- int byteIndex = 0;
+ int byteOffset = 0;
int byteSize = SEGMENT_SIZE;
- while (byteIndex < body.length){
- byteSize = Math.min(byteSize, body.length - byteIndex);
-
- RequestBody requestBody = getRequestBodyWithRange(byteIndex, byteSize);
+ while (byteOffset < body.length){
+ byteSize = Math.min(byteSize, body.length - byteOffset);
+ RequestBody requestBody = getRequestBodyWithRange(byteOffset, byteSize);
requestBody.writeTo(bufferedSink);
bufferedSink.flush();
- byteIndex += byteSize;
+ byteOffset += byteSize;
}
-
}
private RequestBody getRequestBodyWithRange(int location, int size){
byte[] data = Arrays.copyOfRange(body, location, location + size);
- return RequestBody.create(data, contentType());
+ return RequestBody.create(contentType(), data);
}
}
diff --git a/library/src/main/java/com/qiniu/android/http/request/httpclient/SystemHttpClient.java b/library/src/main/java/com/qiniu/android/http/request/httpclient/SystemHttpClient.java
index 9161a8908..9a2c8bf0a 100644
--- a/library/src/main/java/com/qiniu/android/http/request/httpclient/SystemHttpClient.java
+++ b/library/src/main/java/com/qiniu/android/http/request/httpclient/SystemHttpClient.java
@@ -17,6 +17,8 @@
import org.json.JSONObject;
import java.io.IOException;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.ProtocolException;
@@ -56,6 +58,7 @@ public class SystemHttpClient implements IRequestClient {
public static final String JsonMime = "application/json";
public static final String FormMime = "application/x-www-form-urlencoded";
+ private boolean hasHandleComplete = false;
private static ConnectionPool pool;
private Request currentRequest;
private OkHttpClient httpClient;
@@ -73,7 +76,7 @@ public void request(Request request,
metrics = new UploadSingleRequestMetrics();
metrics.clientName = "okhttp";
- metrics.clientVersion = Version.userAgent.replace("okhttp/", "");
+ metrics.clientVersion = getOkHttpVersion();
metrics.setRequest(request);
currentRequest = request;
httpClient = createHttpClient(connectionProxy);
@@ -382,27 +385,32 @@ public void callFailed(Call call, IOException ioe) {
};
}
- private synchronized void handleError(Request request,
- int responseCode,
- String errorMsg,
- RequestClientCompleteHandler complete) {
- if (metrics == null || metrics.response != null) {
- return;
+ private void handleError(Request request,
+ int responseCode,
+ String errorMsg,
+ RequestClientCompleteHandler complete) {
+ synchronized (this) {
+ if (hasHandleComplete) {
+ return;
+ }
+ hasHandleComplete = true;
}
ResponseInfo info = ResponseInfo.create(request, responseCode, null, null, errorMsg);
metrics.response = info;
metrics.request = request;
complete.complete(info, metrics, info.response);
-
releaseResource();
}
- private synchronized void handleResponse(Request request,
- okhttp3.Response response,
- RequestClientCompleteHandler complete) {
- if (metrics == null || metrics.response != null) {
- return;
+ private void handleResponse(Request request,
+ okhttp3.Response response,
+ RequestClientCompleteHandler complete) {
+ synchronized (this) {
+ if (hasHandleComplete) {
+ return;
+ }
+ hasHandleComplete = true;
}
int statusCode = response.code();
@@ -420,7 +428,7 @@ private synchronized void handleResponse(Request request,
String errorMessage = null;
try {
responseBody = response.body().bytes();
- } catch (IOException e) {
+ } catch (Exception e) {
errorMessage = e.getMessage();
}
@@ -509,6 +517,24 @@ private static JSONObject buildJsonResp(byte[] body) throws Exception {
}
+ private static String getOkHttpVersion() {
+ try {
+ Method get = Version.class.getMethod("userAgent");
+ Object version = get.invoke(Version.class);
+ return (version + "").replace("okhttp/", "");
+ } catch (Exception ignore) {
+ }
+
+ try {
+ Field versionField = Version.class.getField("userAgent");
+ Object version = versionField.get(Version.class);
+ return (version + "").replace("okhttp/", "");
+ } catch (Exception ignore) {
+ }
+
+ return "";
+ }
+
private static class ResponseTag {
public String ip = "";
public long duration = -1;
diff --git a/library/src/main/java/com/qiniu/android/http/serverRegion/UploadDomainRegion.java b/library/src/main/java/com/qiniu/android/http/serverRegion/UploadDomainRegion.java
index bc5c51bb4..8c0ec21b7 100644
--- a/library/src/main/java/com/qiniu/android/http/serverRegion/UploadDomainRegion.java
+++ b/library/src/main/java/com/qiniu/android/http/serverRegion/UploadDomainRegion.java
@@ -23,6 +23,8 @@ public class UploadDomainRegion implements IUploadRegion {
// 是否支持http3
private boolean http3Enabled;
+ // 是否使用ipv6
+ private boolean ipv6Enabled;
// 是否冻结过Host,PS:如果没有冻结过 Host,则当前 Region 上传也就不会有错误信息,可能会返回-9,所以必须要再进行一次尝试
private boolean hasFreezeHost;
@@ -88,6 +90,8 @@ public void setupRegionData(ZoneInfo zoneInfo) {
// 暂不开启
http3Enabled = false;
+ ipv6Enabled = zoneInfo.ipv6;
+
ArrayList domainHostList = new ArrayList<>();
if (zoneInfo.domains != null) {
domainHostList.addAll(zoneInfo.domains);
@@ -139,9 +143,14 @@ public IUploadServer getNextServer(UploadRequestState requestState, ResponseInfo
IUploadServer domainServer = domain.getServer(new UploadServerDomain.GetServerCondition() {
@Override
public boolean condition(String host, UploadServer serverP, UploadServer filterServer) {
-
- // 1.1 剔除冻结对象
String filterServerIP = filterServer == null ? null : filterServer.getIp();
+
+ // 1.1 剔除 ipv6
+ if (!ipv6Enabled && Utils.isIpv6(filterServerIP)) {
+ return false;
+ }
+
+ // 1.2 剔除冻结对象
String frozenType = UploadServerFreezeUtil.getFrozenType(host, filterServerIP);
boolean isFrozen = UploadServerFreezeUtil.isTypeFrozenByFreezeManagers(frozenType, new UploadServerFreezeManager[]{UploadServerFreezeUtil.globalHttp3Freezer()});
@@ -149,7 +158,7 @@ public boolean condition(String host, UploadServer serverP, UploadServer filterS
return false;
}
- // 1.2 挑选网络状态最优
+ // 1.3 挑选网络状态最优
return UploadServerNetworkStatus.isServerNetworkBetter(filterServer, serverP);
}
});
@@ -176,8 +185,14 @@ public boolean condition(String host, UploadServer serverP, UploadServer filterS
IUploadServer domainServer = domain.getServer(new UploadServerDomain.GetServerCondition() {
@Override
public boolean condition(String host, UploadServer serverP, UploadServer filterServer) {
- // 1.1 剔除冻结对象
String filterServerIP = filterServer == null ? null : filterServer.getIp();
+
+ // 1.1 剔除 ipv6
+ if (!ipv6Enabled && Utils.isIpv6(filterServerIP)) {
+ return false;
+ }
+
+ // 1.2 剔除冻结对象
String frozenType = UploadServerFreezeUtil.getFrozenType(host, filterServerIP);
boolean isFrozen = UploadServerFreezeUtil.isTypeFrozenByFreezeManagers(frozenType, new UploadServerFreezeManager[]{partialHttp2Freezer, UploadServerFreezeUtil.globalHttp2Freezer()});
@@ -185,7 +200,7 @@ public boolean condition(String host, UploadServer serverP, UploadServer filterS
return false;
}
- // 1.2 挑选网络状态最优
+ // 1.3 挑选网络状态最优
return UploadServerNetworkStatus.isServerNetworkBetter(filterServer, serverP);
}
});
diff --git a/library/src/main/java/com/qiniu/android/storage/BaseUpload.java b/library/src/main/java/com/qiniu/android/storage/BaseUpload.java
index eb364ef32..3cfcf7e61 100644
--- a/library/src/main/java/com/qiniu/android/storage/BaseUpload.java
+++ b/library/src/main/java/com/qiniu/android/storage/BaseUpload.java
@@ -18,7 +18,7 @@ abstract class BaseUpload implements Runnable {
protected final String key;
protected final String fileName;
protected final byte[] data;
- protected final File file;
+ protected final UploadSource uploadSource;
protected final UpToken token;
protected final UploadOptions option;
protected final Configuration config;
@@ -33,7 +33,7 @@ abstract class BaseUpload implements Runnable {
private int currentRegionIndex;
private ArrayList regions;
- private BaseUpload(File file,
+ private BaseUpload(UploadSource source,
byte[] data,
String fileName,
String key,
@@ -43,7 +43,7 @@ private BaseUpload(File file,
Recorder recorder,
String recorderKey,
UpTaskCompletionHandler completionHandler) {
- this.file = file;
+ this.uploadSource = source;
this.data = data;
this.fileName = fileName != null ? fileName : "?";
this.key = key;
@@ -57,7 +57,7 @@ private BaseUpload(File file,
this.initData();
}
- protected BaseUpload(File file,
+ protected BaseUpload(UploadSource source,
String key,
UpToken token,
UploadOptions option,
@@ -65,7 +65,7 @@ protected BaseUpload(File file,
Recorder recorder,
String recorderKey,
UpTaskCompletionHandler completionHandler) {
- this(file, null, file.getName(), key, token, option, config, recorder, recorderKey, completionHandler);
+ this(source, null, source.getFileName(), key, token, option, config, recorder, recorderKey, completionHandler);
}
protected BaseUpload(byte[] data,
@@ -181,6 +181,7 @@ protected void insertRegionAtFirst(IUploadRegion region) {
}
protected boolean switchRegion() {
+
if (regions == null) {
return false;
}
diff --git a/library/src/main/java/com/qiniu/android/storage/ConcurrentResumeUpload.java b/library/src/main/java/com/qiniu/android/storage/ConcurrentResumeUpload.java
index 3f9278a9a..39598950d 100644
--- a/library/src/main/java/com/qiniu/android/storage/ConcurrentResumeUpload.java
+++ b/library/src/main/java/com/qiniu/android/storage/ConcurrentResumeUpload.java
@@ -5,12 +5,13 @@
import com.qiniu.android.utils.StringUtils;
import java.io.File;
+import java.io.InputStream;
class ConcurrentResumeUpload extends PartsUpload {
private GroupTaskThread groupTaskThread;
- protected ConcurrentResumeUpload(File file,
+ protected ConcurrentResumeUpload(UploadSource source,
String key,
UpToken token,
UploadOptions option,
@@ -18,7 +19,7 @@ protected ConcurrentResumeUpload(File file,
Recorder recorder,
String recorderKey,
UpTaskCompletionHandler completionHandler) {
- super(file, key, token, option, config, recorder, recorderKey, completionHandler);
+ super(source, key, token, option, config, recorder, recorderKey, completionHandler);
}
@Override
diff --git a/library/src/main/java/com/qiniu/android/storage/Configuration.java b/library/src/main/java/com/qiniu/android/storage/Configuration.java
index 1dc210470..88ffc5cca 100644
--- a/library/src/main/java/com/qiniu/android/storage/Configuration.java
+++ b/library/src/main/java/com/qiniu/android/storage/Configuration.java
@@ -154,6 +154,14 @@ private KeyGenerator getKeyGen(KeyGenerator keyGen) {
public String gen(String key, File file) {
return key + "_._" + new StringBuffer(file.getAbsolutePath()).reverse();
}
+
+ @Override
+ public String gen(String key, String sourceId) {
+ if (sourceId == null) {
+ sourceId = "";
+ }
+ return key + "_._" + sourceId;
+ }
};
}
return keyGen;
diff --git a/library/src/main/java/com/qiniu/android/storage/FormUpload.java b/library/src/main/java/com/qiniu/android/storage/FormUpload.java
index e8c39d96a..1c52ab9ed 100644
--- a/library/src/main/java/com/qiniu/android/storage/FormUpload.java
+++ b/library/src/main/java/com/qiniu/android/storage/FormUpload.java
@@ -13,7 +13,7 @@
class FormUpload extends BaseUpload {
private boolean isAsync = true;
- private double previousPercent;
+ private final UpProgress upProgress;
private RequestTransaction uploadTransaction;
protected FormUpload(byte[] data,
@@ -24,6 +24,7 @@ protected FormUpload(byte[] data,
Configuration config,
UpTaskCompletionHandler completionHandler) {
super(data, key, fileName, token, option, config, completionHandler);
+ this.upProgress = new UpProgress(this.option.progressHandler);
}
@Override
@@ -36,18 +37,7 @@ protected void startToUpload() {
RequestProgressHandler progressHandler = new RequestProgressHandler() {
@Override
public void progress(long totalBytesWritten, long totalBytesExpectedToWrite) {
- if (option.progressHandler != null){
- double percent = (double)totalBytesWritten / (double)totalBytesExpectedToWrite;
- if (percent > 0.95){
- percent = 0.95;
- }
- if (percent > previousPercent){
- previousPercent = percent;
- } else {
- percent = previousPercent;
- }
- option.progressHandler.progress(key, percent);
- }
+ upProgress.progress(key, totalBytesWritten, totalBytesExpectedToWrite);
}
};
uploadTransaction.uploadFormData(data, fileName, isAsync, progressHandler, new RequestTransaction.RequestCompleteHandler() {
@@ -62,12 +52,7 @@ public void complete(ResponseInfo responseInfo, UploadRegionRequestMetrics reque
return;
}
- AsyncRun.runInMain(new Runnable() {
- @Override
- public void run() {
- option.progressHandler.progress(key, 1.0);
- }
- });
+ upProgress.notifyDone(key, data.length);
completeAction(responseInfo, response);
}
});
diff --git a/library/src/main/java/com/qiniu/android/storage/KeyGenerator.java b/library/src/main/java/com/qiniu/android/storage/KeyGenerator.java
index 00ff525b1..a1043c557 100644
--- a/library/src/main/java/com/qiniu/android/storage/KeyGenerator.java
+++ b/library/src/main/java/com/qiniu/android/storage/KeyGenerator.java
@@ -13,5 +13,27 @@ public interface KeyGenerator {
* @param file 本地文件名
* @return 持久化上传纪录的key
*/
+ @Deprecated
String gen(String key, File file);
+
+ /**
+ * 根据服务器的key和本地文件唯一 ID 生成持久化纪录的key
+ * 如果开启断点续传功能,请确保持久化纪录的 key 相同的文件一定是同一个
+ * SDK 断点续传流程:
+ * 1. 用户调用上传接口上传资源 A
+ * 2. 根据资源 A 信息调用 {@link KeyGenerator#gen(String, String)} 生成持久化纪录的 key
+ * 3. 根据生成持久化纪录的 key 获取本地缓存记录,无缓存则直接走新资源上传流程
+ * 4. 解析缓存记录中的 sourceId 对比当前资源 A 的 sourceId,如果不同则走新资源上传流程
+ * 5. 对比缓存资源的 size 和待上传资源 A 的 size,如果两个 size 均不为 -1 且不相等,
+ * 则走新资源上传流程;size 等于 -1 时,资源 A 为 InputStream 且不知道文件流大小,不验证 size
+ * 6. 断点续传生效,进入断点续传流程
+ *
+ * @param key 服务器的key
+ * @param sourceId 本地文件 ID
+ * File: fileName + modifyTime
+ * Uri: fileName + modifyTime
+ * InputStream: fileName
+ * @return 持久化上传纪录的key
+ */
+ String gen(String key, String sourceId);
}
diff --git a/library/src/main/java/com/qiniu/android/storage/PartsUpload.java b/library/src/main/java/com/qiniu/android/storage/PartsUpload.java
index 7a934f794..5e67e6d32 100644
--- a/library/src/main/java/com/qiniu/android/storage/PartsUpload.java
+++ b/library/src/main/java/com/qiniu/android/storage/PartsUpload.java
@@ -20,7 +20,7 @@ class PartsUpload extends BaseUpload {
private ResponseInfo uploadDataErrorResponseInfo;
private JSONObject uploadDataErrorResponse;
- protected PartsUpload(File file,
+ protected PartsUpload(UploadSource source,
String key,
UpToken token,
UploadOptions option,
@@ -28,7 +28,7 @@ protected PartsUpload(File file,
Recorder recorder,
String recorderKey,
UpTaskCompletionHandler completionHandler) {
- super(file, key, token, option, config, recorder, recorderKey, completionHandler);
+ super(source, key, token, option, config, recorder, recorderKey, completionHandler);
}
@Override
@@ -37,18 +37,18 @@ protected void initData() {
if (config != null && config.resumeUploadVersion == Configuration.RESUME_UPLOAD_VERSION_V1) {
LogUtil.i("key:" + StringUtils.toNonnullString(key) + " 分片V1");
- uploadPerformer = new PartsUploadPerformerV1(file, fileName, key, token, option, config, recorderKey);
+ uploadPerformer = new PartsUploadPerformerV1(uploadSource, fileName, key, token, option, config, recorderKey);
} else {
LogUtil.i("key:" + StringUtils.toNonnullString(key) + " 分片V2");
- uploadPerformer = new PartsUploadPerformerV2(file, fileName, key, token, option, config, recorderKey);
+ uploadPerformer = new PartsUploadPerformerV2(uploadSource, fileName, key, token, option, config, recorderKey);
}
}
boolean isAllUploaded() {
- if (uploadPerformer.fileInfo == null) {
+ if (uploadPerformer.uploadInfo == null) {
return false;
} else {
- return uploadPerformer.fileInfo.isAllUploaded();
+ return uploadPerformer.uploadInfo.isAllUploaded();
}
}
@@ -85,7 +85,7 @@ protected int prepareToUpload() {
LogUtil.i("key:" + StringUtils.toNonnullString(key) + " region:" + StringUtils.toNonnullString(uploadPerformer.currentRegion.getZoneInfo().regionId));
}
- if (file == null || !uploadPerformer.canReadFile()) {
+ if (!uploadPerformer.canReadFile()) {
code = ResponseInfo.LocalIOError;
}
@@ -94,6 +94,11 @@ protected int prepareToUpload() {
@Override
protected boolean switchRegion() {
+ // 重新加载资源,如果加载失败,不可切换 region
+ if (!uploadPerformer.couldReloadInfo() || !uploadPerformer.reloadInfo()) {
+ return false;
+ }
+
boolean isSuccess = super.switchRegion();
if (isSuccess) {
uploadPerformer.switchRegion(getCurrentRegion());
@@ -142,6 +147,13 @@ public void complete() {
return;
}
+ // 只有再读取结束再能知道文件大小,需要检测
+ if (uploadPerformer.uploadInfo.getSourceSize() == 0) {
+ ResponseInfo response = ResponseInfo.zeroSize("file is empty");
+ completeAction(response, null);
+ return;
+ }
+
LogUtil.i("key:" + StringUtils.toNonnullString(key) + " completeUpload");
// 3. 组装文件
@@ -156,12 +168,6 @@ public void complete(ResponseInfo responseInfo, JSONObject response) {
return;
}
- AsyncRun.runInMain(new Runnable() {
- @Override
- public void run() {
- option.progressHandler.progress(key, 1.0);
- }
- });
completeAction(responseInfo, response);
}
});
@@ -282,7 +288,7 @@ private void reportBlock() {
item.setReport(metrics.totalElapsedTime(), ReportItem.BlockKeyTotalElapsedTime);
item.setReport(metrics.bytesSend(), ReportItem.BlockKeyBytesSent);
item.setReport(uploadPerformer.recoveredFrom, ReportItem.BlockKeyRecoveredFrom);
- item.setReport(file.length(), ReportItem.BlockKeyFileSize);
+ item.setReport(uploadSource.getSize(), ReportItem.BlockKeyFileSize);
item.setReport(Utils.getCurrentProcessID(), ReportItem.BlockKeyPid);
item.setReport(Utils.getCurrentThreadID(), ReportItem.BlockKeyTid);
diff --git a/library/src/main/java/com/qiniu/android/storage/PartsUploadPerformer.java b/library/src/main/java/com/qiniu/android/storage/PartsUploadPerformer.java
index 8330af0fb..e29d0fdd4 100644
--- a/library/src/main/java/com/qiniu/android/storage/PartsUploadPerformer.java
+++ b/library/src/main/java/com/qiniu/android/storage/PartsUploadPerformer.java
@@ -6,17 +6,12 @@
import com.qiniu.android.http.request.IUploadRegion;
import com.qiniu.android.http.request.RequestTransaction;
import com.qiniu.android.http.serverRegion.UploadDomainRegion;
-import com.qiniu.android.utils.AsyncRun;
import com.qiniu.android.utils.LogUtil;
import com.qiniu.android.utils.StringUtils;
import org.json.JSONException;
import org.json.JSONObject;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.List;
@@ -26,8 +21,8 @@ abstract class PartsUploadPerformer {
final String key;
final String fileName;
- final File file;
- final RandomAccessFile randomAccessFile;
+ final UploadSource uploadSource;
+ private final UpProgress upProgress;
final UpToken token;
final UploadOptions options;
@@ -37,20 +32,19 @@ abstract class PartsUploadPerformer {
private IUploadRegion targetRegion;
protected IUploadRegion currentRegion;
- private double previousPercent;
Long recoveredFrom;
- UploadFileInfo fileInfo;
+ UploadInfo uploadInfo;
List uploadTransactions;
- PartsUploadPerformer(File file,
+ PartsUploadPerformer(UploadSource uploadSource,
String fileName,
String key,
UpToken token,
UploadOptions options,
Configuration config,
String recorderKey) {
- this.file = file;
+ this.uploadSource = uploadSource;
this.key = key;
this.fileName = fileName;
this.token = token;
@@ -58,46 +52,38 @@ abstract class PartsUploadPerformer {
this.config = config;
this.recorder = config.recorder;
this.recorderKey = recorderKey;
+ this.upProgress = new UpProgress(this.options.progressHandler);
- RandomAccessFile randomAccessFile = null;
- if (file != null) {
- try {
- randomAccessFile = new RandomAccessFile(file, "r");
- } catch (FileNotFoundException ignored) {
- }
- }
- this.randomAccessFile = randomAccessFile;
this.initData();
}
void initData() {
uploadTransactions = new ArrayList<>();
+ uploadInfo = getDefaultUploadInfo();
recoverUploadInfoFromRecord();
- if (fileInfo == null) {
- fileInfo = getDefaultUploadFileInfo();
- }
}
boolean canReadFile() {
- return randomAccessFile != null;
+ return uploadInfo != null && uploadInfo.hasValidResource();
+ }
+
+ boolean couldReloadInfo() {
+ return uploadInfo.couldReloadSource();
+ }
+
+ boolean reloadInfo() {
+ return uploadInfo.reloadSource();
}
void closeFile() {
- if (randomAccessFile != null) {
- try {
- randomAccessFile.close();
- } catch (IOException e) {
- try {
- randomAccessFile.close();
- } catch (IOException ignored) {
- }
- }
+ if (uploadInfo != null) {
+ uploadInfo.close();
}
}
void switchRegion(IUploadRegion region) {
- if (fileInfo != null) {
- fileInfo.clearUploadState();
+ if (uploadInfo != null) {
+ uploadInfo.clearUploadState();
}
currentRegion = region;
recoveredFrom = null;
@@ -106,29 +92,16 @@ void switchRegion(IUploadRegion region) {
}
}
- void notifyProgress() {
- if (fileInfo == null) {
+ void notifyProgress(Boolean isCompleted) {
+ if (uploadInfo == null) {
return;
}
- double percent = fileInfo.progress();
- if (percent > 0.95) {
- percent = 0.95;
- }
- if (percent > previousPercent) {
- previousPercent = percent;
+
+ if (isCompleted) {
+ upProgress.notifyDone(key, uploadInfo.getSourceSize());
} else {
- percent = previousPercent;
+ upProgress.progress(key, uploadInfo.uploadSize(), uploadInfo.getSourceSize());
}
-
- final double notifyPercent = percent;
- AsyncRun.runInMain(new Runnable() {
- @Override
- public void run() {
- if (options != null && options.progressHandler != null) {
- options.progressHandler.progress(key, notifyPercent);
- }
- }
- });
}
void recordUploadInfo() {
@@ -142,10 +115,10 @@ void recordUploadInfo() {
if (currentRegion != null && currentRegion.getZoneInfo() != null) {
zoneInfoJson = currentRegion.getZoneInfo().detailInfo;
}
- if (fileInfo != null) {
- fileInfoJson = fileInfo.toJsonObject();
+ if (uploadInfo != null) {
+ fileInfoJson = uploadInfo.toJsonObject();
}
- if (zoneInfoJson != null && fileInfo != null) {
+ if (zoneInfoJson != null && fileInfoJson != null) {
JSONObject info = new JSONObject();
try {
info.put(kRecordZoneInfoKey, zoneInfoJson);
@@ -162,8 +135,8 @@ void recordUploadInfo() {
void removeUploadInfoRecord() {
recoveredFrom = null;
- if (fileInfo != null) {
- fileInfo.clearUploadState();
+ if (uploadInfo != null) {
+ uploadInfo.clearUploadState();
}
if (recorder != null && recorderKey != null) {
recorder.del(recorderKey);
@@ -180,7 +153,7 @@ void recoverUploadInfoFromRecord() {
" recoverUploadInfoFromRecord");
String key = recorderKey;
- if (recorder == null || key == null || key.length() == 0 || file == null) {
+ if (recorder == null || key == null || key.length() == 0 || uploadSource == null) {
return;
}
@@ -195,21 +168,20 @@ void recoverUploadInfoFromRecord() {
try {
JSONObject info = new JSONObject(new String(data));
ZoneInfo zoneInfo = ZoneInfo.buildFromJson(info.getJSONObject(kRecordZoneInfoKey));
- UploadFileInfo recoverFileInfo = getFileFromJson(info.getJSONObject(kRecordFileInfoKey));
- if (zoneInfo != null && recoverFileInfo != null && !recoverFileInfo.isEmpty() && file != null &&
- recoverFileInfo.size == file.length() &&
- recoverFileInfo.modifyTime == file.lastModified()) {
+ UploadInfo recoverUploadInfo = getUploadInfoFromJson(uploadSource, info.getJSONObject(kRecordFileInfoKey));
+ if (zoneInfo != null && recoverUploadInfo != null && recoverUploadInfo.isValid() && uploadInfo.isSameUploadInfo(recoverUploadInfo)) {
LogUtil.i("key:" + StringUtils.toNonnullString(key) +
" recorderKey:" + StringUtils.toNonnullString(recorderKey) +
" recoverUploadInfoFromRecord valid");
- fileInfo = recoverFileInfo;
+ recoverUploadInfo.checkInfoStateAndUpdate();
+ uploadInfo = recoverUploadInfo;
UploadDomainRegion region = new UploadDomainRegion();
region.setupRegionData(zoneInfo);
currentRegion = region;
targetRegion = region;
- recoveredFrom = (long) ((recoverFileInfo.progress() * recoverFileInfo.size));
+ recoveredFrom = recoverUploadInfo.uploadSize();
} else {
LogUtil.i("key:" + StringUtils.toNonnullString(key) +
" recorderKey:" + StringUtils.toNonnullString(recorderKey) +
@@ -252,9 +224,9 @@ void destroyUploadRequestTransaction(RequestTransaction transaction) {
}
}
- abstract UploadFileInfo getDefaultUploadFileInfo();
+ abstract UploadInfo getDefaultUploadInfo();
- abstract UploadFileInfo getFileFromJson(JSONObject jsonObject);
+ abstract UploadInfo getUploadInfoFromJson(UploadSource source, JSONObject jsonObject);
abstract void serverInit(PartsUploadPerformerCompleteHandler completeHandler);
diff --git a/library/src/main/java/com/qiniu/android/storage/PartsUploadPerformerV1.java b/library/src/main/java/com/qiniu/android/storage/PartsUploadPerformerV1.java
index 9e02249ed..79f6d1046 100644
--- a/library/src/main/java/com/qiniu/android/storage/PartsUploadPerformerV1.java
+++ b/library/src/main/java/com/qiniu/android/storage/PartsUploadPerformerV1.java
@@ -10,35 +10,32 @@
import org.json.JSONException;
import org.json.JSONObject;
-import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
class PartsUploadPerformerV1 extends PartsUploadPerformer {
- private static int BlockSize = 4 * 1024 * 1024;
-
- PartsUploadPerformerV1(File file,
+ PartsUploadPerformerV1(UploadSource uploadSource,
String fileName,
String key,
UpToken token,
UploadOptions options,
Configuration config,
String recorderKey) {
- super(file, fileName, key, token, options, config, recorderKey);
+ super(uploadSource, fileName, key, token, options, config, recorderKey);
}
@Override
- UploadFileInfo getFileFromJson(JSONObject jsonObject) {
+ UploadInfo getUploadInfoFromJson(UploadSource source, JSONObject jsonObject) {
if (jsonObject == null) {
return null;
}
- return UploadFileInfoPartV1.fileFromJson(jsonObject);
+ return UploadInfoV1.infoFromJson(source, jsonObject);
}
@Override
- UploadFileInfo getDefaultUploadFileInfo() {
- return new UploadFileInfoPartV1(file.length(), BlockSize, getUploadChunkSize(), file.lastModified());
+ UploadInfo getDefaultUploadInfo() {
+ return new UploadInfoV1(uploadSource, config);
}
@Override
@@ -49,35 +46,35 @@ void serverInit(PartsUploadPerformerCompleteHandler completeHandler) {
@Override
void uploadNextData(final PartsUploadPerformerDataCompleteHandler completeHandler) {
- UploadFileInfoPartV1 uploadFileInfo = (UploadFileInfoPartV1) fileInfo;
+ UploadInfoV1 info = (UploadInfoV1) uploadInfo;
UploadBlock block = null;
UploadData chunk = null;
synchronized (this) {
- block = uploadFileInfo.nextUploadBlock();
- if (block != null) {
- chunk = block.nextUploadData();
+ try {
+ block = info.nextUploadBlock();
+ chunk = info.nextUploadData(block);
if (chunk != null) {
- chunk.isUploading = true;
- chunk.isCompleted = false;
+ chunk.updateState(UploadData.State.Uploading);
}
- }
- }
- if (block == null || chunk == null) {
- LogUtil.i("key:" + StringUtils.toNonnullString(key) + " no chunk left");
+ } catch (Exception e) {
+ // 此处可能导致后面无法恢复
+ LogUtil.i("key:" + StringUtils.toNonnullString(key) + e.getMessage());
- ResponseInfo responseInfo = ResponseInfo.sdkInteriorError("no chunk left");
- completeHandler.complete(true, responseInfo, null, null);
- return;
+ ResponseInfo responseInfo = ResponseInfo.localIOError(e.getMessage());
+ completeHandler.complete(true, responseInfo, null, null);
+ return;
+ }
}
- chunk.data = getChunkDataWithRetry(chunk, block);
- if (chunk.data == null) {
+ if (block == null || chunk == null) {
LogUtil.i("key:" + StringUtils.toNonnullString(key) + " no chunk left");
-
- chunk.isUploading = false;
- chunk.isCompleted = false;
- ResponseInfo responseInfo = ResponseInfo.localIOError("get data error");
+ ResponseInfo responseInfo = null;
+ if (uploadInfo.getSourceSize() == 0) {
+ responseInfo = ResponseInfo.zeroSize("file is empty");
+ } else {
+ responseInfo = ResponseInfo.sdkInteriorError("no chunk left");
+ }
completeHandler.complete(true, responseInfo, null, null);
return;
}
@@ -87,40 +84,34 @@ void uploadNextData(final PartsUploadPerformerDataCompleteHandler completeHandle
RequestProgressHandler progressHandler = new RequestProgressHandler() {
@Override
public void progress(long totalBytesWritten, long totalBytesExpectedToWrite) {
- uploadChunk.progress = (double) totalBytesWritten / (double) totalBytesExpectedToWrite;
- notifyProgress();
+ uploadChunk.setUploadSize(totalBytesWritten);
+ notifyProgress(false);
}
};
PartsUploadPerformerCompleteHandler completeHandlerP = new PartsUploadPerformerCompleteHandler() {
@Override
public void complete(ResponseInfo responseInfo, UploadRegionRequestMetrics requestMetrics, JSONObject response) {
- uploadChunk.data = null;
-
- String blockContext = null;
+ String ctx = null;
if (response != null) {
try {
- blockContext = response.getString("ctx");
+ ctx = response.getString("ctx");
} catch (JSONException e) {
}
}
- if (responseInfo.isOK() && blockContext != null) {
- uploadBlock.context = blockContext;
- uploadChunk.progress = 1;
- uploadChunk.isUploading = false;
- uploadChunk.isCompleted = true;
+ if (responseInfo.isOK() && ctx != null) {
+ uploadBlock.ctx = ctx;
+ uploadChunk.updateState(UploadData.State.Complete);
recordUploadInfo();
- notifyProgress();
+ notifyProgress(false);
} else {
- uploadChunk.isUploading = false;
- uploadChunk.isCompleted = false;
-
+ uploadChunk.updateState(UploadData.State.WaitToUpload);
}
completeHandler.complete(false, responseInfo, requestMetrics, response);
}
};
- if (uploadChunk.isFirstData()) {
+ if (info.isFirstData(uploadChunk)) {
LogUtil.i("key:" + StringUtils.toNonnullString(key) + " makeBlock");
makeBlock(uploadBlock, uploadChunk, progressHandler, completeHandlerP);
} else {
@@ -131,20 +122,23 @@ public void complete(ResponseInfo responseInfo, UploadRegionRequestMetrics reque
@Override
void completeUpload(final PartsUploadPerformerCompleteHandler completeHandler) {
- UploadFileInfoPartV1 uploadFileInfo = (UploadFileInfoPartV1) fileInfo;
+ UploadInfoV1 info = (UploadInfoV1) uploadInfo;
String[] contexts = null;
- ArrayList contextsList = uploadFileInfo.allBlocksContexts();
+ ArrayList contextsList = info.allBlocksContexts();
if (contextsList != null && contextsList.size() > 0) {
contexts = contextsList.toArray(new String[contextsList.size()]);
}
final RequestTransaction transaction = createUploadRequestTransaction();
- transaction.makeFile(uploadFileInfo.size, fileName, contexts, true, new RequestTransaction.RequestCompleteHandler() {
+ transaction.makeFile(info.getSourceSize(), fileName, contexts, true, new RequestTransaction.RequestCompleteHandler() {
@Override
public void complete(ResponseInfo responseInfo, UploadRegionRequestMetrics requestMetrics, JSONObject response) {
+ if (responseInfo.isOK()) {
+ notifyProgress(true);
+ }
destroyUploadRequestTransaction(transaction);
completeHandler.complete(responseInfo, requestMetrics, response);
}
@@ -173,7 +167,7 @@ private void uploadChunk(final UploadBlock block,
final PartsUploadPerformerCompleteHandler completeHandler) {
final RequestTransaction transaction = createUploadRequestTransaction();
- transaction.uploadChunk(block.context, block.offset, chunk.data, chunk.offset, true, progressHandler, new RequestTransaction.RequestCompleteHandler() {
+ transaction.uploadChunk(block.ctx, block.offset, chunk.data, chunk.offset, true, progressHandler, new RequestTransaction.RequestCompleteHandler() {
@Override
public void complete(ResponseInfo responseInfo, UploadRegionRequestMetrics requestMetrics, JSONObject response) {
@@ -183,54 +177,4 @@ public void complete(ResponseInfo responseInfo, UploadRegionRequestMetrics reque
});
}
-
- private byte[] getChunkDataWithRetry(UploadData chunk, UploadBlock block) {
- byte[] uploadData = null;
-
- int maxTime = 3;
- int index = 0;
- while (index < maxTime) {
- uploadData = getChunkData(chunk, block);
- if (uploadData != null) {
- break;
- }
- index ++;
- }
-
- return uploadData;
- }
-
- private synchronized byte[] getChunkData(UploadData chunk, UploadBlock block) {
- if (randomAccessFile == null || chunk == null || block == null) {
- return null;
- }
- int readSize = 0;
- byte[] data = new byte[chunk.size];
- try {
- randomAccessFile.seek((chunk.offset + block.offset));
- while (readSize < chunk.size) {
- int ret = randomAccessFile.read(data, readSize, (chunk.size - readSize));
- if (ret < 0) {
- break;
- }
- readSize += ret;
- }
-
- // 读数据非预期
- if (readSize != chunk.size) {
- data = null;
- }
- } catch (IOException e) {
- data = null;
- }
- return data;
- }
-
- private int getUploadChunkSize() {
- if (config.useConcurrentResumeUpload) {
- return BlockSize;
- } else {
- return config.chunkSize;
- }
- }
}
diff --git a/library/src/main/java/com/qiniu/android/storage/PartsUploadPerformerV2.java b/library/src/main/java/com/qiniu/android/storage/PartsUploadPerformerV2.java
index a3cad8d56..d968a4e2b 100644
--- a/library/src/main/java/com/qiniu/android/storage/PartsUploadPerformerV2.java
+++ b/library/src/main/java/com/qiniu/android/storage/PartsUploadPerformerV2.java
@@ -4,47 +4,44 @@
import com.qiniu.android.http.metrics.UploadRegionRequestMetrics;
import com.qiniu.android.http.request.RequestTransaction;
import com.qiniu.android.http.request.handler.RequestProgressHandler;
-import com.qiniu.android.utils.Etag;
import com.qiniu.android.utils.LogUtil;
import com.qiniu.android.utils.StringUtils;
import org.json.JSONException;
import org.json.JSONObject;
-import java.io.File;
-import java.io.IOException;
import java.util.List;
import java.util.Map;
class PartsUploadPerformerV2 extends PartsUploadPerformer {
- PartsUploadPerformerV2(File file,
+ PartsUploadPerformerV2(UploadSource uploadSource,
String fileName,
String key,
UpToken token,
UploadOptions options,
Configuration config,
String recorderKey) {
- super(file, fileName, key, token, options, config, recorderKey);
+ super(uploadSource, fileName, key, token, options, config, recorderKey);
}
@Override
- UploadFileInfo getFileFromJson(JSONObject jsonObject) {
+ UploadInfo getUploadInfoFromJson(UploadSource source, JSONObject jsonObject) {
if (jsonObject == null) {
return null;
}
- return UploadFileInfoPartV2.fileFromJson(jsonObject);
+ return UploadInfoV2.infoFromJson(source, jsonObject);
}
@Override
- UploadFileInfo getDefaultUploadFileInfo() {
- return new UploadFileInfoPartV2(file.length(), config.chunkSize, file.lastModified());
+ UploadInfo getDefaultUploadInfo() {
+ return new UploadInfoV2(uploadSource, config);
}
@Override
void serverInit(final PartsUploadPerformerCompleteHandler completeHandler) {
- final UploadFileInfoPartV2 uploadFileInfo = (UploadFileInfoPartV2) fileInfo;
- if (uploadFileInfo != null && uploadFileInfo.isValid()) {
+ final UploadInfoV2 info = (UploadInfoV2) uploadInfo;
+ if (info != null && info.isValid()) {
LogUtil.i("key:" + StringUtils.toNonnullString(key) + " serverInit success");
ResponseInfo responseInfo = ResponseInfo.successResponse();
completeHandler.complete(responseInfo, null, null);
@@ -68,8 +65,8 @@ public void complete(ResponseInfo responseInfo, UploadRegionRequestMetrics reque
}
}
if (responseInfo.isOK() && uploadId != null && expireAt != null) {
- uploadFileInfo.uploadId = uploadId;
- uploadFileInfo.expireAt = expireAt;
+ info.uploadId = uploadId;
+ info.expireAt = expireAt;
recordUploadInfo();
}
completeHandler.complete(responseInfo, requestMetrics, response);
@@ -79,51 +76,52 @@ public void complete(ResponseInfo responseInfo, UploadRegionRequestMetrics reque
@Override
void uploadNextData(final PartsUploadPerformerDataCompleteHandler completeHandler) {
- UploadFileInfoPartV2 uploadFileInfo = (UploadFileInfoPartV2) fileInfo;
+ final UploadInfoV2 info = (UploadInfoV2) uploadInfo;
UploadData data = null;
synchronized (this) {
- data = uploadFileInfo.nextUploadData();
- if (data != null) {
- data.isUploading = true;
- data.isCompleted = false;
+ try {
+ data = info.nextUploadData();
+ if (data != null) {
+ data.updateState(UploadData.State.Uploading);
+ }
+ } catch (Exception e) {
+ // 此处可能无法恢复
+ LogUtil.i("key:" + StringUtils.toNonnullString(key) + " " + e.getMessage());
+
+ ResponseInfo responseInfo = ResponseInfo.localIOError(e.getMessage());
+ completeHandler.complete(true, responseInfo, null, responseInfo.response);
+ return;
}
}
if (data == null) {
LogUtil.i("key:" + StringUtils.toNonnullString(key) + " no data left");
- ResponseInfo responseInfo = ResponseInfo.sdkInteriorError("no data left");
+ ResponseInfo responseInfo = null;
+ if (uploadInfo.getSourceSize() == 0) {
+ responseInfo = ResponseInfo.zeroSize("file is empty");
+ } else {
+ responseInfo = ResponseInfo.sdkInteriorError("no chunk left");
+ }
completeHandler.complete(true, responseInfo, null, null);
return;
}
- data.data = getUploadDataWithRetry(data);
- if (data.data == null) {
- LogUtil.i("key:" + StringUtils.toNonnullString(key) + " get data error");
-
- data.isUploading = false;
- data.isCompleted = false;
- ResponseInfo responseInfo = ResponseInfo.localIOError("get data error");
- completeHandler.complete(true, responseInfo, null, responseInfo.response);
- return;
- }
-
final UploadData uploadData = data;
RequestProgressHandler progressHandler = new RequestProgressHandler() {
@Override
public void progress(long totalBytesWritten, long totalBytesExpectedToWrite) {
- uploadData.progress = (double) totalBytesWritten / (double) totalBytesExpectedToWrite;
- notifyProgress();
+ uploadData.setUploadSize(totalBytesWritten);
+ notifyProgress(false);
}
};
final RequestTransaction transaction = createUploadRequestTransaction();
- transaction.uploadPart(true, uploadFileInfo.uploadId, data.index, data.data, progressHandler, new RequestTransaction.RequestCompleteHandler() {
+ transaction.uploadPart(true, info.uploadId, info.getPartIndexOfData(data), data.data, progressHandler, new RequestTransaction.RequestCompleteHandler() {
@Override
public void complete(ResponseInfo responseInfo, UploadRegionRequestMetrics requestMetrics, JSONObject response) {
- uploadData.data = null;
destroyUploadRequestTransaction(transaction);
String etag = null;
@@ -136,15 +134,12 @@ public void complete(ResponseInfo responseInfo, UploadRegionRequestMetrics reque
}
}
if (responseInfo.isOK() && etag != null && md5 != null) {
- uploadData.progress = 1;
uploadData.etag = etag;
- uploadData.isUploading = false;
- uploadData.isCompleted = true;
+ uploadData.updateState(UploadData.State.Complete);
recordUploadInfo();
- notifyProgress();
+ notifyProgress(false);
} else {
- uploadData.isUploading = false;
- uploadData.isCompleted = false;
+ uploadData.updateState(UploadData.State.WaitToUpload);
}
completeHandler.complete(false, responseInfo, requestMetrics, response);
}
@@ -153,60 +148,21 @@ public void complete(ResponseInfo responseInfo, UploadRegionRequestMetrics reque
@Override
void completeUpload(final PartsUploadPerformerCompleteHandler completeHandler) {
- final UploadFileInfoPartV2 uploadFileInfo = (UploadFileInfoPartV2) fileInfo;
+ final UploadInfoV2 info = (UploadInfoV2) uploadInfo;
- List