AWS S3 Java SDK的文件下载帮助

45

以下代码仅适用于从S3存储桶下载文本文件。对于图像则无法使用。是否有更简单的方法使用AWS SDK来管理下载/类型?文档中提供的示例并不明显。

AWSCredentials myCredentials = new BasicAWSCredentials(
       String.valueOf(Constants.act), String.valueOf(Constants.sk)); 
AmazonS3Client s3Client = new AmazonS3Client(myCredentials);        
S3Object object = s3Client.getObject(new GetObjectRequest("bucket", "file"));
    
BufferedReader reader = new BufferedReader(new InputStreamReader(
       object.getObjectContent()));
File file = new File("localFilename");      
Writer writer = new OutputStreamWriter(new FileOutputStream(file));
    
while (true) {          
     String line = reader.readLine();           
     if (line == null)
          break;            
     
     writer.write(line + "\n");
}
    
writer.close();

我需要做一些事情并尝试您的代码,但找不到jar文件,请问您能否建议使用哪个jar文件。目前我正在使用aws-android-sdk-2.1.5-s3.jar文件,但没有找到所有类。 - Ravi Bhandari
你知道如何将文件上传到亚马逊吗?我正在使用你的代码下载文件,它运行得非常完美。 - Ravi Bhandari
6个回答

70

虽然Mauricio的答案中给出的代码是可行的,他关于流的观点当然是正确的。然而,亚马逊在其SDK中提供了一种更快的保存文件的方法。我不知道它在2011年是否可用,但现在是可用的。

AmazonS3Client s3Client = new AmazonS3Client(myCredentials);

File localFile = new File("localFilename");

ObjectMetadata object = s3Client.getObject(new GetObjectRequest("bucket", "s3FileName"), localFile);

4
需要进行小幅编辑:对象内容已保存到文件中,但返回的对象是ObjectMetadata而非S3Object。请参阅http://docs.amazonwebservices.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/s3/AmazonS3Client.html#getObject%28com.amazonaws.services.s3.model.GetObjectRequest,%20java.io.File%29 - dvs
1
@azdev 实际上,代码示例使用了 getObject 的不同版本,该版本确实返回 S3Object。 - Eyal
为什么我在代码中看不到S3Client.getObject方法?我想实现相同的功能,但我的s3Client对象中没有这样的方法。我是不是漏掉了什么? - Shikha Shah
@ShikhaShah getObject方法返回S3Object是来自AmazonS3接口,由AmazonS3Client实现。也许你的IDE没有显示从接口继承的方法? - Eyal
但是我只能通过AmazonS3Client下载并保存该文件,但是看不到可以加速保存过程的特定方法...我还是很困惑!! - Shikha Shah
你使用的SDK版本是什么?我有一个Maven依赖项到aws-java-sdk,版本1.3.12。 - Eyal

47

你应该使用 InputStreamOutputStream 类,而不是 ReaderWriter 类:

InputStream reader = new BufferedInputStream(
   object.getObjectContent());
File file = new File("localFilename");      
OutputStream writer = new BufferedOutputStream(new FileOutputStream(file));

int read = -1;

while ( ( read = reader.read() ) != -1 ) {
    writer.write(read);
}

writer.flush();
writer.close();
reader.close();

1
这个有效。AWS文档列出的程序不起作用。这个工作得非常好。谢谢您的发布。 - R-JANA

18

Eyals的回答让你有了一半的进展,但并不是很清楚,所以我来澄清一下。

AmazonS3Client s3Client = new AmazonS3Client(myCredentials);

//This is where the downloaded file will be saved
File localFile = new File("localFilename");

//This returns an ObjectMetadata file but you don't have to use this if you don't want 
s3Client.getObject(new GetObjectRequest(bucketName, id.getId()), localFile);

//Now your file will have your image saved 
boolean success = localFile.exists() && localFile.canRead(); 

你用了什么来获取id.getId()的值? - Teraiya Mayur
id.getId() 是您用于将对象存储在桶中的键。我只是使用我的 ID 作为键,因为我知道它是唯一的。总之,您创建一个空文件,执行 getRequest 告诉 AWS API 新的空文件在哪里,AWS API 处理将对象写入您指定的文件。如此方便。 - Shawn Vader
@ShawnVader:请问您为什么要验证文件,S3 API不是已经进行了哈希检查吗?谢谢。 - saurabheights
1
@saurabheights 你是对的,检查文件的上述示例可能会返回不正确的结果,因为在上述情况下 localFile 存在是可以接受的。也许更好的方法是确保返回的 ObjectMetadata 不为空。文档中说:> 返回指定对象的所有 S3 对象元数据。如果指定了约束条件但未满足,则返回 null。因此,如果它具有元数据,则可以确信它是文件中有效内容,因为通过查看 AWS 源代码,我可以看到它验证了文件完整性并在失败之前重试一次。 - Shawn Vader
@ShawnVader:已编辑答案,请您在同行评审后再次查看。 - saurabheights

4

有更简单的方法可以实现这一点。我使用了下面的片段,参考了http://docs.ceph.com/docs/mimic/radosgw/s3/java/

AmazonS3 s3client = AmazonS3ClientBuilder.standard()
                .withCredentials(new AWSStaticCredentialsProvider(credentials)).withRegion(Regions.US_EAST_1).build();

s3client.getObject(
                new GetObjectRequest("nomad-prop-pics", "Documents/1.pdf"),
                new File("D:\\Eka-Contract-Physicals-Dev\\Contracts-Physicals\\utility-service\\downlods\\1.pdf")
    );

2
使用java.nio.file.FilesS3Object复制到本地文件。
public File getFile(String fileName) throws Exception {
    if (StringUtils.isEmpty(fileName)) {
        throw new Exception("file name can not be empty");
    }
    S3Object s3Object = amazonS3.getObject("bucketname", fileName);
    if (s3Object == null) {
        throw new Exception("Object not found");
    }
    File file = new File("you file path");
    Files.copy(s3Object.getObjectContent(), file.toPath());
    return file;
}

inputStream是从哪里来的?我想你可能指的是s3Object.close或者s3Object.getObjectContent.close()。无论如何,nio是一个不错的建议。 - Kramer

0

依赖项 AWS S3 存储桶

implementation "commons-logging:commons-logging-api:1.1"
implementation platform('com.amazonaws:aws-java-sdk-bom:1.11.1000')
implementation 'com.amazonaws:aws-android-sdk-core:2.6.0'
implementation 'com.amazonaws:aws-android-sdk-cognito:2.2.0'
implementation 'com.amazonaws:aws-android-sdk-s3:2.6.0'

从S3存储桶下载对象并存储在本地存储中。

try {
                //Creating credentials
                AWSCredentials awsCredentials = new BasicAWSCredentials(AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY);

                //Creating S3
                AmazonS3Client s3Client = new AmazonS3Client(awsCredentials);

                //Creating file path
                File dir = new File(this.getExternalFilesDir("AWS"),"FolderName");
                if(!dir.exists()){
                    dir.mkdir();
                }

                //Object Key
                String bucketName = "*** Bucket Name ***";
                String objKey = "*** Object Key ***";
                
                //Get File Name from Object key
                String  name = objKey.substring(objKey.lastIndexOf('/') + 1);

                //Storing file S3 object in file path
                InputStream in = s3Client.getObject(new GetObjectRequest(bucketName, objKey)).getObjectContent();
                Files.copy(in,Paths.get(dir.getAbsolutePath()+"/"+name));
                in.close();

            } catch (Exception e) {
                Log.e("TAG", "onCreate: " + e);
            }

从S3 Bucket获取对象列表

public void getListOfObject()
    {
        ListObjectsV2Result result ;
        AWSCredentials awsCredentials = new BasicAWSCredentials(AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY);
        AmazonS3Client s3Client = new AmazonS3Client(awsCredentials);
        result = s3Client.listObjectsV2(AWS_BUCKET);
        for( S3ObjectSummary s3ObjectSummary : result.getObjectSummaries())
        {
            Log.e("TAG", "onCreate: "+s3ObjectSummary.getKey() );
        }
    }

检查对象是否存在于存储桶中

public String isObjectAvailable(String object_key)
    {

        try {
            AWSCredentials awsCredentials = new BasicAWSCredentials(AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY);
            AmazonS3 s3 = new AmazonS3Client(awsCredentials);
            String bucketName = AWS_BUCKET;
            S3Object object = s3.getObject(bucketName, object_key);
            Log.e("TAG", "isObjectAvailable: "+object.getKey()+","+object.getBucketName() );
        } catch (AmazonServiceException e) {
            String errorCode = e.getErrorCode();
            if (!errorCode.equals("NoSuchKey")) {
               // throw e;
                Log.e("TAG", "isObjectAvailable: "+e );
            }

            return "no such key";
        }
        return "null";
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接