【1】创建目录对象
创建文件–带有文件目录 如 test1/test3/hello.txt
。如果目标对象已经存在,则会进行覆盖。
AmazonS3 singleAmazonS3 = this.getSingleAmazonS3(); // 创建文件--带有文件目录 如 test1/test3/hello.txt Bucket bucket = cosFileSystem.getBucket(singleAmazonS3); singleAmazonS3.putObject(bucket.getName(),"test1/test3/hello.txt",new File("./hello.txt"));
通过控制台登录查看,会看到如下结构:
注意,这里目标对象的key建议不要以/开头,否则bucket内会有一个目录/,这个不符合COS的规范。比如/test1/test3/hello.txt,其最终效果不是我们想象的test1 -- test3 目录下有个hello.txt,而是/ -- test1---test3 下有个hello.txt。
对象名称如果带有目录,那么应该是a/b/hello.txt格式,a\b\hello.txt格式是错误的,不支持的。
【2】获取文件对象
① 通过key直接获取文件对象本身
假设文件对象名称为test1/test4/hello.txt
,那么如下所示可以拿到文件对象然后包装为流。之后就是最基本的IO操作了,可以实现文件下载。
S3Object amazonS3Object = singleAmazonS3.getObject(bucket.getName(), "test1/test4/hello.txt"); S3ObjectInputStream objectInputStream = amazonS3Object.getObjectContent(); BufferedInputStream bufferedInputStream = new BufferedInputStream(objectInputStream);
② 获取文件下载链接
如下所示根据桶名称和文件对象名称获取文件下载链接,然后通过HttpURLConnection 获取流。
Bucket bucket = getBucket(singleAmazonS3); GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucket.getName(), "test1/test4/hello.txt"); URL url = singleAmazonS3.generatePresignedUrl(request); logger.debug("{}生成的文件下载链接为:{}",saveName,url); HttpURLConnection connection = (HttpURLConnection)url.openConnection(); connection.setConnectTimeout(15000); connection.connect(); InputStream urlInputStream = connection.getInputStream();
③ 判断文件对象是否存
doesObjectExist可以用来判断文件对象是否存在。
AmazonS3 singleAmazonS3 = this.getSingleAmazonS3(); Bucket bucket = singleAmazonS3.listBuckets().get(0); // true or false boolean exist = singleAmazonS3.doesObjectExist(bucket.getName(), "111.txt");
④ public权限文件下载
如果文件是public,则直接使用如下方式获取URL即可。
// 针对 public 权限即可使用这种方式下载 URL url = singleAmazonS3.getUrl(bucketName, key);
【3】获取对象
① listObjects(bucketName);
azon SDK提供的S3读取接口listObjects(bucketName)是分页读取,默认每次返回1000个对象。
ObjectListing objectListing = singleAmazonS3.listObjects(bucketName);
那么objectSummaries 又是什么呢?这里存储了我们文件具体对象。
//存储所有对象 List<S3ObjectSummary> objectSummaries =Collections.emptyList(); //获取到客户端 AmazonS3 singleAmazonS3 = getSingleAmazonS3(); private void getAllS3ObjectSummary(AmazonS3 singleAmazonS3 ,String bucketName) { //获取第一批 ObjectListing current= singleAmazonS3.listObjects(bucketName); this.objectSummaries.addAll(current.getObjectSummaries());//第一页 while (current.isTruncated()) { //翻页 current = singleAmazonS3.listNextBatchOfObjects(current); //直到最后一页 this.objectSummaries.addAll(current.getObjectSummaries()); } }
S3ObjectSummary如下所示,包含了桶名称,文件在桶内存储的key(其实就是文件的全路径),eTag(MD5加密的一个签名),size(大小),lastModified(最后修改时间),storageClass(Amazon S3用来存储该对象的类)以及owner(对象所属者)。
② listNextBatchOfObjects(ObjectListing previousObjectListing)
其实就是基于上一页进行翻页,在①中我们也进行了说明。marker表示到哪个对象为止,是个闭区间。比如下图中的marker对应的对象是上一页中的,nextMarker对应的对象是本页中的。
需要说明的是当你像使用这个方法进行分页的话,建议使用isTruncated()
先判断一下是否有下一页。如果该方法返回true,则再建翻页。示例如下:
ObjectListing listObjects = singleAmazonS3.listObjects(bucketName); // 如果没有下一页,那么listObjects.isTruncated() 将会返回false while (listObjects.isTruncated()){ ObjectListing objectListing = singleAmazonS3.listNextBatchOfObjects(listObjects); }
③ listObjects(String bucketName, String prefix)
与①中listObjects(String bucketName)不同的是这里多了prefix,也就是说这里以某个前缀目录为基准进行读取。默认①中prefix是"",也就是根目录。
如下所示,我们获取0033d435/下的对象。
ObjectListing listObjects = singleAmazonS3.listObjects(bucketName, "0033d435/");
【4】异常解决
(1) No content length specified for stream data. Stream contents will be buffered in memory and could
// 原始上传 singleAmazonS3.putObject(bucket.getName(), saveName,inputStream , new ObjectMetadata()); //修改为如下 -也就是说给objectMetadata设置长度 ObjectMetadata objectMetadata = new ObjectMetadata(); objectMetadata.setContentLength(inputStream.available()); singleAmazonS3.putObject(bucket.getName(), saveName,inputStream , objectMetadata);