Skip to content

Commit 417439a

Browse files
authored
Merge pull request #206 from sxci/add_uc
Add uc
2 parents 6e84d91 + d3d623c commit 417439a

File tree

13 files changed

+633
-31
lines changed

13 files changed

+633
-31
lines changed

src/main/java/com/qiniu/common/Config.java

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,22 @@ public final class Config {
3232
* 默认文件服务器
3333
*/
3434
public static String IO_HOST = "http://iovip.qbox.me";
35+
3536
/**
36-
* 默认Zone
37+
* 获取上传地址服务器
3738
*/
38-
public static Zone zone = Zone.zone0();
39+
public static String UC_HOST = "https://uc.qbox.me";
40+
41+
/**
42+
* 使用的Zone, 若不指定,通过七牛服务自动判断
43+
*/
44+
public static Zone zone = null;
45+
46+
/**
47+
* 上传是否使用 https , 默认否
48+
*/
49+
public static boolean UPLOAD_BY_HTTPS = false;
50+
3951
/**
4052
* 如果文件大小大于此值则使用断点上传, 否则使用Form上传
4153
*/
@@ -67,5 +79,6 @@ public final class Config {
6779

6880
private Config() {
6981
}
82+
7083
}
7184
// CHECKSTYLE:ON

src/main/java/com/qiniu/common/Zone.java

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,27 @@ public final class Zone {
1414
public final String upHostBackup;
1515

1616
public Zone(String upHost, String upHostBackup) {
17-
this.upHost = upHost;
18-
this.upHostBackup = upHostBackup;
17+
this.upHost = upHost.trim();
18+
this.upHostBackup = upHostBackup.trim();
19+
}
20+
21+
@Override
22+
public int hashCode() {
23+
return upHost.hashCode() * upHostBackup.hashCode();
24+
}
25+
26+
@Override
27+
public boolean equals(Object obj) {
28+
if (obj instanceof Zone) {
29+
Zone that = (Zone) obj;
30+
return that.upHost.equals(this.upHost) && that.upHostBackup.equals(this.upHostBackup);
31+
}
32+
return super.equals(obj);
33+
}
34+
35+
@Override
36+
public String toString() {
37+
return super.toString() + ", upHost: " + this.upHost + ", upHostBackup: " + this.upHostBackup;
1938
}
2039

2140
public static Zone zone0() {

src/main/java/com/qiniu/http/Response.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ private Response(okhttp3.Response response, int statusCode, String reqId, String
6363
this.body = body;
6464
}
6565

66-
static Response create(okhttp3.Response response, String address, double duration) {
66+
public static Response create(okhttp3.Response response, String address, double duration) {
6767
String error = null;
6868
int code = response.code();
6969
String reqId = null;

src/main/java/com/qiniu/storage/FormUploader.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
package com.qiniu.storage;
22

3-
import com.qiniu.common.Config;
43
import com.qiniu.common.QiniuException;
54
import com.qiniu.http.AsyncCallback;
65
import com.qiniu.http.Client;
76
import com.qiniu.http.Response;
87
import com.qiniu.util.Crc32;
98
import com.qiniu.util.StringMap;
9+
import com.qiniu.util.UC;
1010

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

5757
void asyncUpload(final UpCompletionHandler handler) throws IOException {
5858
buildParams();
5959
if (data != null) {
60-
client.asyncMultipartPost(Config.zone.upHost, params, "file", fileName,
60+
client.asyncMultipartPost(UC.zone(token).upHost, params, "file", fileName,
6161
data, mime, new StringMap(), new AsyncCallback() {
6262
@Override
6363
public void complete(Response r) {
@@ -66,7 +66,7 @@ public void complete(Response r) {
6666
});
6767
return;
6868
}
69-
client.asyncMultipartPost(Config.zone.upHost, params, "file", fileName,
69+
client.asyncMultipartPost(UC.zone(token).upHost, params, "file", fileName,
7070
file, mime, new StringMap(), new AsyncCallback() {
7171
@Override
7272
public void complete(Response r) {

src/main/java/com/qiniu/storage/ResumeUploader.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import com.qiniu.storage.model.ResumeBlockInfo;
99
import com.qiniu.util.StringMap;
1010
import com.qiniu.util.StringUtils;
11+
import com.qiniu.util.UC;
1112
import com.qiniu.util.UrlSafeBase64;
1213

1314
import java.io.File;
@@ -55,7 +56,6 @@ public final class ResumeUploader {
5556
this.size = file.length();
5657
this.params = params;
5758
this.mime = mime == null ? Client.DefaultMime : mime;
58-
this.host = Config.zone.upHost;
5959
long count = (size + Config.BLOCK_SIZE - 1) / Config.BLOCK_SIZE;
6060
this.contexts = new String[(int) count];
6161
this.blockBuffer = new byte[Config.BLOCK_SIZE];
@@ -66,6 +66,9 @@ public final class ResumeUploader {
6666
}
6767

6868
public Response upload() throws QiniuException {
69+
if (host == null) {
70+
this.host = UC.zone(upToken).upHost;
71+
}
6972
long uploaded = helper.recoveryFromRecord();
7073
try {
7174
this.file = new FileInputStream(f);
@@ -95,7 +98,7 @@ public Response upload() throws QiniuException {
9598
response = makeBlock(blockBuffer, blockSize);
9699
} catch (QiniuException e) {
97100
if (e.code() < 0) {
98-
host = Config.zone.upHostBackup;
101+
host = UC.zone(upToken).upHostBackup;
99102
}
100103
if (e.response == null || e.response.needRetry()) {
101104
retry = true;

src/main/java/com/qiniu/util/Auth.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,8 @@ public String uploadToken(String bucket, String key, long expires, StringMap pol
248248
return uploadTokenWithDeadline(bucket, key, deadline, policy, strict);
249249
}
250250

251-
String uploadTokenWithDeadline(String bucket, String key, long deadline, StringMap policy, boolean strict) {
251+
public String uploadTokenWithDeadline(String bucket, String key, long deadline, StringMap policy, boolean strict) {
252+
// TODO UpHosts Global
252253
String scope = bucket;
253254
if (key != null) {
254255
scope = bucket + ":" + key;
Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
package com.qiniu.util;
2+
3+
import com.qiniu.common.Config;
4+
import com.qiniu.common.QiniuException;
5+
import com.qiniu.common.Zone;
6+
import okhttp3.OkHttpClient;
7+
import okhttp3.Request;
8+
import okhttp3.Response;
9+
10+
import java.util.List;
11+
import java.util.Map;
12+
import java.util.concurrent.ConcurrentHashMap;
13+
import java.util.concurrent.TimeUnit;
14+
15+
/**
16+
* Created by Simon on 6/22/16.
17+
*/
18+
public class UC {
19+
private Map<AKBKT, ZoneInfo> zones = new ConcurrentHashMap();
20+
21+
private OkHttpClient client = new OkHttpClient.Builder()
22+
.connectTimeout(10000, TimeUnit.SECONDS)
23+
.readTimeout(10000, TimeUnit.SECONDS)
24+
.writeTimeout(10000, TimeUnit.SECONDS).build();
25+
26+
private UC() {
27+
28+
}
29+
30+
private static UC uc = new UC();
31+
32+
public static Zone zone(String ak, String bkt) throws QiniuException {
33+
return uc.getZone(Config.zone, ak, bkt, Config.UPLOAD_BY_HTTPS);
34+
}
35+
36+
public static Zone zone(String uptoken) throws QiniuException {
37+
try {
38+
// http://developer.qiniu.com/article/developer/security/upload-token.html
39+
// http://developer.qiniu.com/article/developer/security/put-policy.html
40+
String[] strings = uptoken.split(":");
41+
String ak = strings[0];
42+
String policy = new String(UrlSafeBase64.decode(strings[2]), Config.UTF_8);
43+
String bkt = Json.decode(policy).get("scope").toString().split(":")[0];
44+
return zone(ak, bkt);
45+
} catch (QiniuException e) {
46+
throw e;
47+
} catch (Exception e) {
48+
throw new QiniuException(e);
49+
}
50+
}
51+
52+
53+
public static String ucVal(String ak, String bkt) throws QiniuException {
54+
// 不解析返回的值,此时 isHttps (Config.UPLOAD_BY_HTTPS) 无实际意义
55+
return uc.getUCVal(ak, bkt, Config.UPLOAD_BY_HTTPS);
56+
}
57+
58+
/**
59+
* 清除缓存。比如空间迁移到不同机房后调用此方法
60+
*/
61+
public static void clear() {
62+
uc.zones.clear();
63+
}
64+
65+
/**
66+
* 返回 java-sdk 中需要的 zone 对象
67+
*/
68+
private Zone getZone(final Zone userSetZone, final String ak, final String bkt, boolean isHttps)
69+
throws QiniuException {
70+
if (userSetZone != null) {
71+
return userSetZone;
72+
}
73+
ZoneInfo zoneInfo = getZoneInfo(ak, bkt, isHttps);
74+
return zoneInfo.zone;
75+
}
76+
77+
/**
78+
* 返回 uc.qbox.me 的原始字符串
79+
*/
80+
public String getUCVal(final String ak, final String bkt, boolean isHttps) throws QiniuException {
81+
ZoneInfo zoneInfo = getZoneInfo(ak, bkt, isHttps);
82+
return zoneInfo.ucjson;
83+
}
84+
85+
86+
ZoneInfo getZoneInfo(final String ak, final String bkt, boolean isHttps) throws QiniuException {
87+
final AKBKT akbkt = new AKBKT(ak, bkt, isHttps);
88+
ZoneInfo zoneInfo = zones.get(akbkt);
89+
90+
if (zoneInfo != null) {
91+
return zoneInfo;
92+
} else {
93+
build(akbkt);
94+
zoneInfo = zones.get(akbkt);
95+
return zoneInfo;
96+
}
97+
}
98+
99+
private void build(AKBKT akbkt) throws QiniuException {
100+
try {
101+
String address = Config.UC_HOST + "/v1/query?ak=" + akbkt.ak + "&bucket=" + akbkt.bkt;
102+
long start = System.currentTimeMillis();
103+
Response res = client.newCall(new Request.Builder()
104+
.url(address)
105+
.build()).execute();
106+
double duration = (System.currentTimeMillis() - start) / 1000.0;
107+
build(akbkt, res, address, duration);
108+
} catch (QiniuException e) {
109+
throw e;
110+
} catch (Exception e) {
111+
throw new QiniuException(e);
112+
}
113+
}
114+
115+
private void build(AKBKT akbkt, Response res, String address, double duration) throws QiniuException {
116+
com.qiniu.http.Response qnRes = com.qiniu.http.Response.create(res, address, duration);
117+
if (!qnRes.isOK()) {
118+
throw new QiniuException(qnRes);
119+
}
120+
try {
121+
String ucVal = qnRes.bodyString();
122+
UCRet ret = qnRes.jsonToObject(UCRet.class);
123+
124+
List<String> args = null;
125+
if (akbkt.isHttps) {
126+
args = ret.https.get("up");
127+
} else {
128+
args = ret.http.get("up");
129+
}
130+
131+
String[] zoneArgs = new String[2];
132+
zoneArgs[0] = getZoneHost(args.get(0));
133+
if (args.size() > 1) {
134+
zoneArgs[1] = getZoneHost(args.get(1));
135+
}
136+
if (zoneArgs[1] == null) {
137+
zoneArgs[1] = zoneArgs[0];
138+
}
139+
140+
Zone new_zone = new Zone(zoneArgs[0], zoneArgs[1]);
141+
142+
if (zoneArgs[0] == null || zoneArgs[0].trim().length() == 0
143+
|| new_zone == null || ucVal == null) {
144+
throw new QiniuException(qnRes);
145+
}
146+
147+
zones.put(akbkt, new ZoneInfo(new_zone, ucVal));
148+
} catch (QiniuException e) {
149+
throw e;
150+
} catch (Exception e) {
151+
throw new QiniuException(e);
152+
}
153+
}
154+
155+
156+
private String getZoneHost(String p) {
157+
if (p.startsWith("http")) {
158+
return p;
159+
} else {
160+
return null;
161+
}
162+
}
163+
164+
private class AKBKT {
165+
String ak;
166+
String bkt;
167+
boolean isHttps;
168+
169+
AKBKT(String ak, String bkt, boolean isHttps) {
170+
this.ak = ak.trim();
171+
this.bkt = bkt.trim();
172+
this.isHttps = isHttps;
173+
}
174+
175+
@Override
176+
public int hashCode() {
177+
return ak.hashCode() * bkt.hashCode() * (isHttps ? 5 : 1);
178+
}
179+
180+
@Override
181+
public boolean equals(Object obj) {
182+
if (obj instanceof AKBKT) {
183+
AKBKT that = (AKBKT) obj;
184+
return this.bkt.equals(that.bkt) && this.ak.equals(that.ak) && (this.isHttps == that.isHttps);
185+
}
186+
return false;
187+
}
188+
}
189+
190+
private class ZoneInfo {
191+
public final String ucjson;
192+
public final Zone zone;
193+
194+
ZoneInfo(Zone zone, String ucjson) {
195+
this.zone = zone;
196+
this.ucjson = ucjson;
197+
}
198+
}
199+
200+
private class UCRet {
201+
Map<String, List<String>> http;
202+
Map<String, List<String>> https;
203+
}
204+
205+
}

0 commit comments

Comments
 (0)