在阿里云OSS使用过程中,一般都是服务器端配置账号密钥 发起上传请求至客户端。不过现在项目一般都是 B/S或者 C/S结构,有时候我们需要从客户端或者浏览器端上传文件,那么先需要将文件从客户端上传至服务器端,然后再从服务器端上传至OSS。在这个过程中,一份数据需要在网络上传输两次,对服务器的带宽压力比较大。不过如果直接从客户端上传,那么也要OSS账号密钥的安全性。
今天我们介绍如何授权第三方直接上传文件到OSS而不通过服务器端转发,减轻服务器端的压力,以及保证OSS的账号安全。目前授权上传有两种实现方式:URL签名和临时访问凭证。我们采用的是URL签名的方式。
pom 文件添加
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>2.7.0</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.3</version>
</dependency>
生成授权Url签名以及上传文件
public static void upload() throws Exception {
String endpoint = "http://oss-cn-hangzhou.aliyuncs.com";
String accessKeyId = "xxx";
String accessKeySecret = "xxx";
String bucketName = "xxx-center-cloud";
String objectName = "23/234234783/48/357918432.reg";
OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
// 生成签名URL。
GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucketName, objectName, HttpMethod.PUT);
// 设置过期时间。
Date expiration = new Date(System.currentTimeMillis() + 1000 * 60 * 2);
request.setExpiration(expiration);
// 设置Content-Type。
request.setContentType("application/octet-stream;charset=utf-8");
// 生成签名URL(HTTP PUT请求)。
URL signedUrl = ossClient.generatePresignedUrl(request);
//使用httpClient模拟客户端 通过http put请求将文件上传上去
CloseableHttpClient httpclient = HttpClients.createDefault();
HttpPut httppost = new HttpPut(signedUrl.toURI());
RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(200000).setSocketTimeout(200000).build();
httppost.setHeader("Content-type", "application/octet-stream;charset=utf-8");
httppost.setConfig(requestConfig);
//文件放进http请求的 body里
HttpEntity reqEntity = new FileEntity(new File("C:\\xxx\\vvvv.txt"));
httppost.setEntity(reqEntity);
CloseableHttpResponse response = httpclient.execute(httppost);
HttpEntity resEntity = response.getEntity();
if (resEntity != null) {
String responseEntityStr = EntityUtils.toString(response.getEntity());
System.out.println(responseEntityStr);
System.out.println("Response content length: " + resEntity.getContentLength());
}
EntityUtils.consume(resEntity);
response.close();
httpclient.close();
}
生成授权Url签名+oss上传回调
public static void uploadAndCallback() throws Exception {
String endpoint = "http://oss-cn-hangzhou.aliyuncs.com";
String accessKeyId = "xxx";
String accessKeySecret = "xxx";
String bucketName = "xxx-center-cloud";
String objectName = "23/234234783/48/357918432.reg";
//上传回调参数
Map callbackMap = new HashMap<String,String>(){{
//回调URL
put("callbackUrl", "http://33gaac.natappfree.cc/appCenter/swyCallback.action");
put( "callbackHost", "33gaac.natappfree.cc");
// 设置发起回调时请求body的值, mimeType size这两个参数oss自动填充,其他为自定义参数。
put("callbackBody", "{'mimeType':${mimeType},'size':${size},'filekey':${x:filekey},'path':${x:path}}");
// 设置发起回调请求的Content-Type。
put("callbackBodyType", "application/json");
}};
//设置发起回调请求的自定义参数,由Key和Value组成,Key必须以x:开始, 与callbackBody中使用到的key相对应
Map callbackVarMap = new HashMap<String,String>(){{
put("x:filekey", "23/234234783/48/");
put("x:path", "357918432.reg");
}};
//上传回调的内容与参数需要进行base64编码
String callbackBase64 = Base64.getEncoder().encodeToString(JSON.toJSONString(callbackMap).getBytes());
String callbackVarBase64X = Base64.getEncoder().encodeToString(JSON.toJSONString(callbackVarMap).getBytes());
OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
// 生成签名URL。
GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucketName, objectName, HttpMethod.PUT);
// 设置过期时间。
Date expiration = new Date(System.currentTimeMillis() + 1000 * 60 * 2);
request.setExpiration(expiration);
// 设置Content-Type。
request.setContentType("application/octet-stream;charset=utf-8");
//将上传回调参数放入header参加签名计算
Map hmap = Maps.newHashMap();
hmap.put("x-oss-callback", callbackBase64);
hmap.put("x-oss-callback-var", callbackVarBase64X);
request.setHeaders(hmap);
// 添加用户自定义元信息。
//request.addUserMetadata("author", "aliy");
// 生成签名URL(HTTP PUT请求)。
URL signedUrl = ossClient.generatePresignedUrl(request);
System.out.println("---------" + signedUrl);
//使用httpClient模拟客户端 通过http put请求将文件上传上去
CloseableHttpClient httpclient = HttpClients.createDefault();
HttpPut httppost = new HttpPut(signedUrl.toURI());
RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(200000).setSocketTimeout(200000).build();
httppost.setHeader("Content-type", "application/octet-stream;charset=utf-8");
//上传回调参数
httppost.setHeader("x-oss-callback", callbackBase64);
httppost.setHeader("x-oss-callback-var", callbackVarBase64X);
httppost.setConfig(requestConfig);
//文件放进http请求的 body里
HttpEntity reqEntity = new FileEntity(new File("C:\\xxx\\vvvv.txt"));
httppost.setEntity(reqEntity);
System.out.println("executing request " + httppost.getRequestLine());
CloseableHttpResponse response = httpclient.execute(httppost);
System.out.println(response.getStatusLine());
HttpEntity resEntity = response.getEntity();
if (resEntity != null) {
String responseEntityStr = EntityUtils.toString(response.getEntity());
System.out.println(responseEntityStr);
System.out.println("Response content length: " + resEntity.getContentLength());
}
EntityUtils.consume(resEntity);
response.close();
httpclient.close();
}