Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Up v2 #472

Open
wants to merge 17 commits into
base: master
Choose a base branch
from
50 changes: 30 additions & 20 deletions src/main/java/com/qiniu/storage/FixBlockUploader.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,13 @@ public class FixBlockUploader {
private String host = null;

/**
* @param blockSize must be multiples of 4M.
* @param blockSize must be >= 4 * 1024 * 1024.
sxci marked this conversation as resolved.
Show resolved Hide resolved
* @param configuration Nullable, if null, then create a new one.
* @param client Nullable, if null, then create a new one with configuration.
* @param recorder Nullable.
*/
public FixBlockUploader(int blockSize, Configuration configuration, Client client, Recorder recorder) {
assert blockSize > 0 && blockSize % (4 * 1024 * 1024) == 0 : "blockSize must be multiples of 4M ";
assert blockSize >= 4 * 1024 * 1024 : "blockSize must be >= 4M ";

if (configuration == null) {
configuration = new Configuration();
Expand Down Expand Up @@ -107,9 +107,9 @@ Response upload(BlockData blockData, Token token, String key, OptionsMeta params
/*
上传到七牛存储保存的文件名, 需要进行UrlSafeBase64编码。
注意:
当设置为空时表示空的文件名;
当设置为未进行 UrlSafeBase64 编码的字符 ~ 的时候,表示未设置文件名,
具体行为如分片上传v1: 使用文件的hash最为文件名, 如果设置了saveKey则使用saveKey的规则进行文件命名
当 key 为空 "" 时表示空的文件名,正常进行 url_safe_base64 编码;
当 key 为未进行 UrlSafeBase64 编码的字符 ~ 的时候表示未设置文件名,
具体行为如分片上传v1: 使用文件的 hash 作为文件名, 如果设置了saveKey则使用saveKey的规则进行文件命名
*/
String base64Key = key != null ? UrlSafeBase64.encodeToString(key) : "~";
String recordFileKey = (recorder == null) ? "NULL"
Expand All @@ -120,12 +120,15 @@ Response upload(BlockData blockData, Token token, String key, OptionsMeta params
host = configHelper.upHost(token.getUpToken());
}
UploadRecordHelper recordHelper = new UploadRecordHelper(recorder, recordFileKey, blockData.repeatable());
// 1. initParts
Record record = initUpload(blockData, recordHelper, bucket, base64Key, token);
boolean repeatable = recorder != null && blockData.repeatable();

Response res;
try {
// 2. uploadPart
upBlock(blockData, token, bucket, base64Key, repeatable, record, pool, maxRunningBlock);
// 3. completeParts
res = makeFile(bucket, base64Key, token, record.uploadId, record.etagIdxes,
blockData.getFileName(), params);
} catch (QiniuException e) {
Expand Down Expand Up @@ -154,14 +157,15 @@ record = null;
}

if (record == null || record.uploadId == null) {
String uploadId = init(bucket, base64Key, token.getUpToken());
InitRet ret = init(bucket, base64Key, token.getUpToken());

List<EtagIdx> etagIdxes = new ArrayList<>();
record = initRecord(uploadId, etagIdxes);
record = initRecord(ret, etagIdxes);
}
return record;
}

String init(String bucket, String base64Key, String upToken) throws QiniuException {
InitRet init(String bucket, String base64Key, String upToken) throws QiniuException {
String url = host + "/buckets/" + bucket + "/objects/" + base64Key + "/uploads";
byte[] data = new byte[0];
StringMap headers = new StringMap().put("Authorization", "UpToken " + upToken);
Expand Down Expand Up @@ -205,9 +209,9 @@ String init(String bucket, String base64Key, String upToken) throws QiniuExcepti
}

try {
String uploadId = res.jsonToMap().get("uploadId").toString();
if (uploadId.length() > 10) {
return uploadId;
InitRet ret = res.jsonToObject(InitRet.class);
if (ret != null && ret.uploadId != null && ret.uploadId.length() > 10 && ret.expireAt > 1000) {
return ret;
}
} catch (Exception e) {
// ignore, see next line
Expand Down Expand Up @@ -432,7 +436,7 @@ Response makeFile(String bucket, String base64Key, Token token, String uploadId,
String fileName, OptionsMeta params) throws QiniuException {
String url = host + "/buckets/" + bucket + "/objects/" + base64Key + "/uploads/" + uploadId;
final StringMap headers = new StringMap().put("Authorization", "UpToken " + token.getUpToken());
sortAsc(etags);
sortByPartNumberAsc(etags);
byte[] data = new MakefileBody(etags, fileName, params)
.json().getBytes(Charset.forName("UTF-8"));

Expand Down Expand Up @@ -493,7 +497,7 @@ private String parseBucket(String upToken) throws QiniuException {
}
}

static void sortAsc(List<EtagIdx> etags) {
static void sortByPartNumberAsc(List<EtagIdx> etags) {
Collections.sort(etags, new Comparator<EtagIdx>() {
@Override
public int compare(EtagIdx o1, EtagIdx o2) {
Expand Down Expand Up @@ -567,17 +571,19 @@ public String toString() {


class Record {
long createdTime;
// second
long expireAt;
String uploadId;
long size;
List<EtagIdx> etagIdxes;
}


Record initRecord(String uploadId, List<EtagIdx> etagIdxes) {
Record initRecord(InitRet ret, List<EtagIdx> etagIdxes) {
Record record = new Record();
record.createdTime = System.currentTimeMillis();
record.uploadId = uploadId;
record.uploadId = ret.uploadId;
//// 服务端 7 天内有效,设置 5 天 ////
record.expireAt = ret.expireAt - 3600 * 24 * 2;
record.size = 0;
record.etagIdxes = etagIdxes != null ? etagIdxes : new ArrayList<EtagIdx>();

Expand Down Expand Up @@ -620,15 +626,14 @@ public void delRecord() {

public void syncRecord(Record record) {
if (needRecord && recorder != null && record.etagIdxes.size() > 0) {
sortAsc(record.etagIdxes);
sortByPartNumberAsc(record.etagIdxes);
recorder.set(recordFileKey, new Gson().toJson(record).getBytes(Charset.forName("UTF-8")));
}
}

public boolean isActiveRecord(Record record, BlockData blockData) {
//// 服务端 7 天内有效,设置 5 天 ////
boolean isOk = record != null
&& record.createdTime > System.currentTimeMillis() - 1000 * 3600 * 24 * 5
&& record.expireAt < (System.currentTimeMillis() / 1000)
&& !StringUtils.isNullOrEmpty(record.uploadId)
&& record.etagIdxes != null && record.etagIdxes.size() > 0
&& record.size > 0 && record.size <= blockData.size();
Expand All @@ -652,6 +657,11 @@ public boolean isActiveRecord(Record record, BlockData blockData) {

///////////////////////////////////////

class InitRet {
String uploadId;
long expireAt;
}


abstract static class BlockData {
protected final int blockDataSize;
Expand Down
13 changes: 12 additions & 1 deletion src/test/java/test/com/qiniu/storage/FixBlockUploaderTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

import static junit.framework.TestCase.assertTrue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;

public class FixBlockUploaderTest {
int blockSize = 1024 * 1024 * 8;
Expand All @@ -45,6 +46,17 @@ private void init2(boolean useHttpsDomains) {
bm = new BucketManager(TestConfig.testAuth, config);
}

@Test
public void testInit() {
Configuration config = new Configuration();
Client client = new Client(config);
try {
new FixBlockUploader(1024 * 1024 * 3, config, client, null);
fail("block size must be >= 1024 * 1024 * 4");
} catch (AssertionError e) {
assertTrue(e.getMessage().indexOf("blockSize must be >= 4M") > -1);
}
}

@Test
public void testEmpty() throws IOException {
Expand Down Expand Up @@ -278,5 +290,4 @@ class MyRet {
public String mimeType;
public String biu2biu;
}

}