文章目录
- Java
- 添加 Maven 依赖
- 文件操作类
- Android
- 依赖
- 调用
- 4 个工具类
Java
添加 Maven 依赖
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.qcloud</groupId>
<artifactId>cos_api</artifactId>
<version>5.2.4</version>
</dependency>
文件操作类
package top.qingrang;
import com.qcloud.cos.COSClient;
import com.qcloud.cos.ClientConfig;
import com.qcloud.cos.auth.BasicCOSCredentials;
import com.qcloud.cos.auth.COSCredentials;
import com.qcloud.cos.model.GetObjectRequest;
import com.qcloud.cos.model.PutObjectRequest;
import com.qcloud.cos.region.Region;
import com.qcloud.cos.transfer.Download;
import com.qcloud.cos.transfer.TransferManager;
import com.qcloud.cos.transfer.Upload;
import java.io.File;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* 腾讯 COS
* 文件的上传,下载,删除
*/
public class App {
static String bucketName = "daily"; //桶的名称
// static String key = "/2018-11-06_200028.jpg"; //上传到云上路径
static String region = "ap-chengdu";//区域成都
static String appId = "1252869435"; //APPID
static COSCredentials cred = null;
static TransferManager transferManager = null;
static COSClient cosClient = null;
static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm ss");
static {
// 1 初始化用户身份信息(secretId, secretKey)
String SecretId = "XXXXXXX"; //SecretId 是用于标识 API 调用者的身份
String SecretKey = "XXXXXXX"; //SecretKey是用于加密签名字符串和服务器端验证签名字符串的密钥
cred = new BasicCOSCredentials(SecretId, SecretKey);
// 2 设置bucket的区域,
ClientConfig clientConfig = new ClientConfig(new Region(region));
// 3 生成cos客户端
cosClient = new COSClient(cred, clientConfig);
// 指定要上传到 COS 上的路径
ExecutorService threadPool = Executors.newFixedThreadPool(32);
// 传入一个 threadpool, 若不传入线程池, 默认 TransferManager 中会生成一个单线程的线程池。
transferManager = new TransferManager(cosClient, threadPool);
}
public static void main(String[] args) {
String name = "2018-11-06-2.png";
String ikey = "/" + name;
String path = "C:\\Users\\123\\Desktop\\" + name;
//上传
upload(key,path);
cosClient.shutdown();
}
/**
* 上传,重复则覆盖
*/
public static void upload(final String key, final String path) {
new Thread(new Runnable() {
public void run() {
try {
System.out.println("上传开始时间:" + sdf.format(new Date()));
// .....(提交上传下载请求, 如下文所属)
// bucket 的命名规则为{name}-{appid} ,此处填写的存储桶名称必须为此格式
String bucket = bucketName + "-" + appId;
//本地文件路径
File localFile = new File(path);
PutObjectRequest putObjectRequest = new PutObjectRequest(bucket, key, localFile);
// 本地文件上传
Upload upload = transferManager.upload(putObjectRequest);
// 异步(如果想等待传输结束,则调用 waitForUploadResult)
//UploadResult uploadResult = upload.waitForUploadResult();
//同步的等待上传结束waitForCompletion
upload.waitForCompletion();
System.out.println("上传结束时间:" + sdf.format(new Date()));
System.out.println("上传成功");
//获取上传成功之后文件的下载地址
URL url = cosClient.generatePresignedUrl(bucketName + "-" + appId, key, new Date(new Date().getTime() + 5 * 60 * 10000));
System.out.println(url);
} catch (Throwable tb) {
System.out.println("上传失败");
tb.printStackTrace();
} finally {
// 关闭 TransferManger
transferManager.shutdownNow();
}
}
}).start();
}
/**
* 下载
*/
public static void download(String key) {
try {
//下载到本地指定路径
File localDownFile = new File("src/test/resources/download.pdf");
GetObjectRequest getObjectRequest = new GetObjectRequest(bucketName + "-" + appId, key);
// 下载文件
Download download = transferManager.download(getObjectRequest, localDownFile);
// 等待传输结束(如果想同步的等待上传结束,则调用 waitForCompletion)
download.waitForCompletion();
System.out.println("下载成功");
} catch (Throwable tb) {
System.out.println("下载失败");
tb.printStackTrace();
} finally {
// 关闭 TransferManger
transferManager.shutdownNow();
}
}
/**
* 删除
*/
public static void delete(final String key) {
new Thread(new Runnable() {
public void run() {
// 指定要删除的 bucket 和路径
try {
cosClient.deleteObject(bucketName + "-" + appId, key);
System.out.println("删除成功");
} catch (Throwable tb) {
System.out.println("删除文件失败");
tb.printStackTrace();
}
}
}).start();
}
}
Android
在这里采用的是 json SDK,其实官方已不推荐了,最好是采用 xml 的方式,具体可以查看官网文档。
先添加 2 个依赖和下面的 4 个工具类,先在 BizService.java
中配置 cos 信息,然后在需要的地方调用 upload()
,即可。
依赖
// 腾讯 COS
compile 'com.tencent.cos:cos:4.3.2+@aar'
compile 'com.squareup.okhttp3:okhttp:3.2.0'
调用
TencentCos.java
import com.ds.groupon.cos.BizService;
import com.ds.groupon.cos.PutObjectSample;
import com.tencent.cos.utils.FileUtils;
public class TencentCos {
/**
* 上传图片到 腾讯 COS
* @param path /storage/emulated/0/temp/xx.jpg
*/
public static void upload(final BizService bizService, final String path) {
new Thread(new Runnable() {
@Override
public void run() {
String cosPath = "/" + FileUtils.getFileName(path); // cos 上的路径,文件名
PutObjectSample.putObjectForSamllFile(bizService, cosPath, path);
}
}).start();
}
}
4 个工具类
BizService
import android.content.Context;
import com.tencent.cos.COSClient;
import com.tencent.cos.COSConfig;
/**
* Created by bradyxiao on 2017/4/11.
* author bradyxiao
*/
public class BizService {
/**
* cos的appid
*/
public String appid;
/**
* appid的一个空间名称
*/
public String bucket;
/**
* cos sdk 的用户接口
*/
public COSClient cosClient;
/**
* 设置园区;根据创建的cos空间时选择的园区
* 华南园区:gz 或 COSEndPoint.COS_GZ(已上线)
* 华北园区:tj 或 COSEndPoint.COS_TJ(已上线)
* 华东园区:sh 或 COSEndPoint.COS_SH
*/
public String region;
/**
* cos sdk 配置设置; 根据需要设置
*/
private COSConfig config;
private static BizService bizService;
private BizService() {
}
private static byte[] syncObj = new byte[0];
public static BizService instance() {
synchronized (syncObj) {
if (bizService == null) {
bizService = new BizService();
}
return bizService;
}
}
public void init(Context context) {
synchronized (this) {
if (cosClient == null) {
config = new COSConfig();
region = "cd";
config.setEndPoint(region);
appid = "xxx";
bucket = "daily";
cosClient = new COSClient(context, appid, config, "");
}
}
}
/**
* 本地签名
*
* @return
*/
public String getLocalSign() {
String secretId = "xxx";
String secretKey = "xxx";
LocalCredentialProvider localCredentialProvider = new LocalCredentialProvider(secretKey);
return localCredentialProvider.getSign(appid, bucket, secretId, null, 60 * 60);
}
public String getSign() {
return getLocalSign();
}
}
PutObjectSample
import android.util.Log;
import com.tencent.cos.model.COSRequest;
import com.tencent.cos.model.COSResult;
import com.tencent.cos.model.PutObjectRequest;
import com.tencent.cos.model.PutObjectResult;
import com.tencent.cos.task.listener.IUploadTaskListener;
/**
* Created by bradyxiao on 2017/4/11.
* author bradyxiao
*/
public class PutObjectSample {
/**
* 简单文件上传 : <20M的文件,直接上传
*/
public static void putObjectForSamllFile(BizService bizService, String cosPath, String localPath) {
/** PutObjectRequest 请求对象 */
PutObjectRequest putObjectRequest = new PutObjectRequest();
/** 设置Bucket */
putObjectRequest.setBucket(bizService.bucket);
/** 设置cosPath :远程路径*/
putObjectRequest.setCosPath(cosPath);
String key = "Pic-Operations";
String value = "{\"rules\":[{\"fileid\":\"tpg_test.tpg\",\"rule\":\"imageView2/format/tpg\"}]}";
putObjectRequest.setCustomerHeaders(key, value);
/** 设置srcPath: 本地文件的路径 */
putObjectRequest.setSrcPath(localPath);
/** 设置sign: 签名,此处使用多次签名 */
putObjectRequest.setSign(bizService.getSign());
/** 设置sha: 是否上传文件时带上sha,一般不需要带*/
//putObjectRequest.setSha("hhhehhdehx");
/** 设置listener: 结果回调 */
putObjectRequest.setListener(new IUploadTaskListener() {
@Override
public void onProgress(COSRequest cosRequest, long currentSize, long totalSize) {
long progress = ((long) ((100.00 * currentSize) / totalSize));
Log.w("XIAO", "progress =" + progress + "%");
}
@Override
public void onCancel(COSRequest cosRequest, COSResult cosResult) {
String result = "上传出错: ret =" + cosResult.code + "; msg =" + cosResult.msg;
Log.w("XIAO", result);
}
@Override
public void onSuccess(COSRequest cosRequest, COSResult cosResult) {
PutObjectResult putObjectResult = (PutObjectResult) cosResult;
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(" 上传结果: ret=" + putObjectResult.code + "; msg =" + putObjectResult.msg + "\n");
stringBuilder.append(" access_url= " + putObjectResult.access_url == null ? "null" : putObjectResult.access_url + "\n");
stringBuilder.append(" resource_path= " + putObjectResult.resource_path == null ? "null" : putObjectResult.resource_path + "\n");
stringBuilder.append(" url= " + putObjectResult.url == null ? "null" : putObjectResult.url);
stringBuilder.append("image_info =" + putObjectResult.imageInfo);
String result = stringBuilder.toString();
Log.w("XIAO", result);
}
@Override
public void onFailed(COSRequest cosRequest, COSResult cosResult) {
String result = "上传出错: ret =" + cosResult.code + "; msg =" + cosResult.msg
+ "; requestId =" + cosResult.requestId;
Log.e("XIAO", result);
}
});
/** 发送请求:执行 */
bizService.cosClient.putObject(putObjectRequest);
}
}
LocalCredentialProvider
import android.util.Base64;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Random;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
/**
* 本地签名类
*
* 用户可以使用这个类本地生成签名,但主要用于测试,为了安全性,正式版本请在第三方服务器上获取签名
*/
public class LocalCredentialProvider extends AbsCredentialProvider{
public LocalCredentialProvider(String secretKey) {
super(secretKey);
}
@Override
protected String encrypt(String source) {
String sign = "";
byte[] hmacSha1 = hmacSha1(source, secretKey);
if (hmacSha1==null) {
return "";
}
try {
byte[] urlByte = source.getBytes("utf-8");
byte[] signByte = new byte[hmacSha1.length+urlByte.length];
System.arraycopy(hmacSha1, 0, signByte, 0, hmacSha1.length);
System.arraycopy(urlByte, 0, signByte, hmacSha1.length, urlByte.length);
sign = Base64.encodeToString(signByte, Base64.DEFAULT);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
sign = sign.replaceAll("\n", "");
return sign;
}
private byte[] hmacSha1(String url, String secreteKey) {
byte[] hmacSha1 = null;
try {
byte[] byteKey = secreteKey.getBytes("utf-8");
SecretKey hmacKey = new SecretKeySpec(byteKey, "HmacSHA1");
Mac mac = Mac.getInstance("HmacSHA1");
mac.init(hmacKey);
hmacSha1 = mac.doFinal(url.getBytes("utf-8"));
} catch (UnsupportedEncodingException e) {
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
}
return hmacSha1;
}
/**
*
* @param appid
* @param bucket
* @param secretId
* @param fileId
* @param expiredTimes: expired time(s).
* @return
*/
public String getSource(String appid, String bucket, String secretId,
String fileId, long expiredTimes){
StringBuilder source = new StringBuilder();
/**
* 形如:1) a=[appid]&b=[bucket]&k=[SecretID]&e=[expiredTime]&t=[currentTime]&r=[rand]&f=;
* 2) a=[appid]&b=[bucket]&k=[SecretID]&e=[expiredTime]&t=[currentTime]&r=[rand]&f=[fileid];
* 3) 其中检测签名时与各个字段的排序顺序无关;
*
* 签名类型:
* 1)下载(不开启token防盗链) 不验证签名
* 2) 上传 多次有效签名
3)查询目录、文件 多次有效签名
4)创建目录 多次有效签名
5)下载(开启token防盗链) 多次有效签名
6)删除目录、文件 单次有效签名
7)更新目录、文件 单次有效签名
*/
source.append("a=" + appid);
source.append("&b=" + bucket);
source.append("&k=" + secretId);
long random = Math.abs(new Random().nextLong());
source.append("&r=" + random);
long t = System.currentTimeMillis()/1000;
if(fileId == null){
expiredTimes = t + expiredTimes;
source.append("&e=" + expiredTimes);
source.append("&t=" + t);
source.append("&f=");
}else {
source.append("&e=" + 0);
source.append("&t=" + t);
fileId = "/" + appid + "/" + bucket + fileId;
fileId = urlEncoder(fileId);
source.append("&f=" + fileId);
}
return source.toString();
}
/**
*对fileID进行URLEncoder编码
*/
private String urlEncoder(String fileID){
if(fileID == null){
return null;
}
StringBuilder stringBuilder = new StringBuilder();
String[] strFiled = fileID.trim().split("/");
int length = strFiled.length;
for(int i = 0; i< length; i++){
if("".equals(strFiled[i]))continue;
stringBuilder.append("/");
try{
String str = URLEncoder.encode(strFiled[i], "utf-8").replace("+","%20");
stringBuilder.append(str);
}catch (Exception e){
e.printStackTrace();
}
}
if(fileID.endsWith("/")) stringBuilder.append("/");
fileID = stringBuilder.toString();
return fileID;
}
public String getSign(String appid, String bucket, String secretId,
String fileId, long expiredTimes){
return encrypt(getSource(appid, bucket, secretId, fileId, expiredTimes));
}
}
AbsCredentialProvider
/**
* 签名抽象类,用户需要实现这个类将原始串转化为签名串
*/
public abstract class AbsCredentialProvider {
protected String secretKey;
public AbsCredentialProvider(String secretKey) {
this.secretKey = secretKey;
}
/**
* 签名函数:将原始字符串进行加密,具体的加密算法见文档
* @param source 原始串
* @return 签名串
*/
protected abstract String encrypt(String source);
}