Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions src/main/java/com/qiniu/common/Config.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,22 @@ public final class Config {
* 默认文件服务器
*/
public static String IO_HOST = "http://iovip.qbox.me";

/**
* 默认Zone
* 获取上传地址服务器
*/
public static Zone zone = Zone.zone0();
public static String UC_HOST = "https://uc.qbox.me";

/**
* 使用的Zone, 若不指定,通过七牛服务自动判断
*/
public static Zone zone = null;

/**
* 上传是否使用 https , 默认否
*/
public static boolean UPLOAD_BY_HTTPS = false;

/**
* 如果文件大小大于此值则使用断点上传, 否则使用Form上传
*/
Expand Down Expand Up @@ -67,5 +79,6 @@ public final class Config {

private Config() {
}

}
// CHECKSTYLE:ON
23 changes: 21 additions & 2 deletions src/main/java/com/qiniu/common/Zone.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,27 @@ public final class Zone {
public final String upHostBackup;

public Zone(String upHost, String upHostBackup) {
this.upHost = upHost;
this.upHostBackup = upHostBackup;
this.upHost = upHost.trim();
this.upHostBackup = upHostBackup.trim();
}

@Override
public int hashCode() {
return upHost.hashCode() * upHostBackup.hashCode();
}

@Override
public boolean equals(Object obj) {
if (obj instanceof Zone) {
Zone that = (Zone) obj;
return that.upHost.equals(this.upHost) && that.upHostBackup.equals(this.upHostBackup);
}
return super.equals(obj);
}

@Override
public String toString() {
return super.toString() + ", upHost: " + this.upHost + ", upHostBackup: " + this.upHostBackup;
}

public static Zone zone0() {
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/qiniu/http/Response.java
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ private Response(okhttp3.Response response, int statusCode, String reqId, String
this.body = body;
}

static Response create(okhttp3.Response response, String address, double duration) {
public static Response create(okhttp3.Response response, String address, double duration) {
String error = null;
int code = response.code();
String reqId = null;
Expand Down
10 changes: 5 additions & 5 deletions src/main/java/com/qiniu/storage/FormUploader.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package com.qiniu.storage;

import com.qiniu.common.Config;
import com.qiniu.common.QiniuException;
import com.qiniu.http.AsyncCallback;
import com.qiniu.http.Client;
import com.qiniu.http.Response;
import com.qiniu.util.Crc32;
import com.qiniu.util.StringMap;
import com.qiniu.util.UC;

import java.io.File;
import java.io.IOException;
Expand Down Expand Up @@ -49,15 +49,15 @@ private FormUploader(Client client, String upToken, String key, byte[] data, Fil
Response upload() throws QiniuException {
buildParams();
if (data != null) {
return client.multipartPost(Config.zone.upHost, params, "file", fileName, data, mime, new StringMap());
return client.multipartPost(UC.zone(token).upHost, params, "file", fileName, data, mime, new StringMap());
}
return client.multipartPost(Config.zone.upHost, params, "file", fileName, file, mime, new StringMap());
return client.multipartPost(UC.zone(token).upHost, params, "file", fileName, file, mime, new StringMap());
}

void asyncUpload(final UpCompletionHandler handler) throws IOException {
buildParams();
if (data != null) {
client.asyncMultipartPost(Config.zone.upHost, params, "file", fileName,
client.asyncMultipartPost(UC.zone(token).upHost, params, "file", fileName,
data, mime, new StringMap(), new AsyncCallback() {
@Override
public void complete(Response r) {
Expand All @@ -66,7 +66,7 @@ public void complete(Response r) {
});
return;
}
client.asyncMultipartPost(Config.zone.upHost, params, "file", fileName,
client.asyncMultipartPost(UC.zone(token).upHost, params, "file", fileName,
file, mime, new StringMap(), new AsyncCallback() {
@Override
public void complete(Response r) {
Expand Down
7 changes: 5 additions & 2 deletions src/main/java/com/qiniu/storage/ResumeUploader.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import com.qiniu.storage.model.ResumeBlockInfo;
import com.qiniu.util.StringMap;
import com.qiniu.util.StringUtils;
import com.qiniu.util.UC;
import com.qiniu.util.UrlSafeBase64;

import java.io.File;
Expand Down Expand Up @@ -55,7 +56,6 @@ public final class ResumeUploader {
this.size = file.length();
this.params = params;
this.mime = mime == null ? Client.DefaultMime : mime;
this.host = Config.zone.upHost;
long count = (size + Config.BLOCK_SIZE - 1) / Config.BLOCK_SIZE;
this.contexts = new String[(int) count];
this.blockBuffer = new byte[Config.BLOCK_SIZE];
Expand All @@ -66,6 +66,9 @@ public final class ResumeUploader {
}

public Response upload() throws QiniuException {
if (host == null) {
this.host = UC.zone(upToken).upHost;
}
long uploaded = helper.recoveryFromRecord();
try {
this.file = new FileInputStream(f);
Expand Down Expand Up @@ -95,7 +98,7 @@ public Response upload() throws QiniuException {
response = makeBlock(blockBuffer, blockSize);
} catch (QiniuException e) {
if (e.code() < 0) {
host = Config.zone.upHostBackup;
host = UC.zone(upToken).upHostBackup;
}
if (e.response == null || e.response.needRetry()) {
retry = true;
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/com/qiniu/util/Auth.java
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,8 @@ public String uploadToken(String bucket, String key, long expires, StringMap pol
return uploadTokenWithDeadline(bucket, key, deadline, policy, strict);
}

String uploadTokenWithDeadline(String bucket, String key, long deadline, StringMap policy, boolean strict) {
public String uploadTokenWithDeadline(String bucket, String key, long deadline, StringMap policy, boolean strict) {
// TODO UpHosts Global
String scope = bucket;
if (key != null) {
scope = bucket + ":" + key;
Expand Down
205 changes: 205 additions & 0 deletions src/main/java/com/qiniu/util/UC.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
package com.qiniu.util;

import com.qiniu.common.Config;
import com.qiniu.common.QiniuException;
import com.qiniu.common.Zone;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

/**
* Created by Simon on 6/22/16.
*/
public class UC {
private Map<AKBKT, ZoneInfo> zones = new ConcurrentHashMap();

private OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(10000, TimeUnit.SECONDS)
.readTimeout(10000, TimeUnit.SECONDS)
.writeTimeout(10000, TimeUnit.SECONDS).build();

private UC() {

}

private static UC uc = new UC();

public static Zone zone(String ak, String bkt) throws QiniuException {
return uc.getZone(Config.zone, ak, bkt, Config.UPLOAD_BY_HTTPS);
}

public static Zone zone(String uptoken) throws QiniuException {
try {
// http://developer.qiniu.com/article/developer/security/upload-token.html
// http://developer.qiniu.com/article/developer/security/put-policy.html
String[] strings = uptoken.split(":");
String ak = strings[0];
String policy = new String(UrlSafeBase64.decode(strings[2]), Config.UTF_8);
String bkt = Json.decode(policy).get("scope").toString().split(":")[0];
return zone(ak, bkt);
} catch (QiniuException e) {
throw e;
} catch (Exception e) {
throw new QiniuException(e);
}
}


public static String ucVal(String ak, String bkt) throws QiniuException {
// 不解析返回的值,此时 isHttps (Config.UPLOAD_BY_HTTPS) 无实际意义
return uc.getUCVal(ak, bkt, Config.UPLOAD_BY_HTTPS);
}

/**
* 清除缓存。比如空间迁移到不同机房后调用此方法
*/
public static void clear() {
uc.zones.clear();
}

/**
* 返回 java-sdk 中需要的 zone 对象
*/
private Zone getZone(final Zone userSetZone, final String ak, final String bkt, boolean isHttps)
throws QiniuException {
if (userSetZone != null) {
return userSetZone;
}
ZoneInfo zoneInfo = getZoneInfo(ak, bkt, isHttps);
return zoneInfo.zone;
}

/**
* 返回 uc.qbox.me 的原始字符串
*/
public String getUCVal(final String ak, final String bkt, boolean isHttps) throws QiniuException {
ZoneInfo zoneInfo = getZoneInfo(ak, bkt, isHttps);
return zoneInfo.ucjson;
}


ZoneInfo getZoneInfo(final String ak, final String bkt, boolean isHttps) throws QiniuException {
final AKBKT akbkt = new AKBKT(ak, bkt, isHttps);
ZoneInfo zoneInfo = zones.get(akbkt);

if (zoneInfo != null) {
return zoneInfo;
} else {
build(akbkt);
zoneInfo = zones.get(akbkt);
return zoneInfo;
}
}

private void build(AKBKT akbkt) throws QiniuException {
try {
String address = Config.UC_HOST + "/v1/query?ak=" + akbkt.ak + "&bucket=" + akbkt.bkt;
long start = System.currentTimeMillis();
Response res = client.newCall(new Request.Builder()
.url(address)
.build()).execute();
double duration = (System.currentTimeMillis() - start) / 1000.0;
build(akbkt, res, address, duration);
} catch (QiniuException e) {
throw e;
} catch (Exception e) {
throw new QiniuException(e);
}
}

private void build(AKBKT akbkt, Response res, String address, double duration) throws QiniuException {
com.qiniu.http.Response qnRes = com.qiniu.http.Response.create(res, address, duration);
if (!qnRes.isOK()) {
throw new QiniuException(qnRes);
}
try {
String ucVal = qnRes.bodyString();
UCRet ret = qnRes.jsonToObject(UCRet.class);

List<String> args = null;
if (akbkt.isHttps) {
args = ret.https.get("up");
} else {
args = ret.http.get("up");
}

String[] zoneArgs = new String[2];
zoneArgs[0] = getZoneHost(args.get(0));
if (args.size() > 1) {
zoneArgs[1] = getZoneHost(args.get(1));
}
if (zoneArgs[1] == null) {
zoneArgs[1] = zoneArgs[0];
}

Zone new_zone = new Zone(zoneArgs[0], zoneArgs[1]);

if (zoneArgs[0] == null || zoneArgs[0].trim().length() == 0
|| new_zone == null || ucVal == null) {
throw new QiniuException(qnRes);
}

zones.put(akbkt, new ZoneInfo(new_zone, ucVal));
} catch (QiniuException e) {
throw e;
} catch (Exception e) {
throw new QiniuException(e);
}
}


private String getZoneHost(String p) {
if (p.startsWith("http")) {
return p;
} else {
return null;
}
}

private class AKBKT {
String ak;
String bkt;
boolean isHttps;

AKBKT(String ak, String bkt, boolean isHttps) {
this.ak = ak.trim();
this.bkt = bkt.trim();
this.isHttps = isHttps;
}

@Override
public int hashCode() {
return ak.hashCode() * bkt.hashCode() * (isHttps ? 5 : 1);
}

@Override
public boolean equals(Object obj) {
if (obj instanceof AKBKT) {
AKBKT that = (AKBKT) obj;
return this.bkt.equals(that.bkt) && this.ak.equals(that.ak) && (this.isHttps == that.isHttps);
}
return false;
}
}

private class ZoneInfo {
public final String ucjson;
public final Zone zone;

ZoneInfo(Zone zone, String ucjson) {
this.zone = zone;
this.ucjson = ucjson;
}
}

private class UCRet {
Map<String, List<String>> http;
Map<String, List<String>> https;
}

}
Loading