文章目录

  • 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);
}