Mr.
Mr.

Reputation: 10122

Amazon Web Services (AWS) S3 Java create a sub directory (object)

I am familiar with AWS Java SDK, I also tried to browse the corresponding Javadoc, but I could not realize how do I create a sub directory, i.e., a directory object within a bucket, and how do I upload files to it.

Assume bucketName and dirName correspond to already existing bucket (with public permission) and a new (object) directory which needs to be created within the bucket (i.e. bucketName/dirName/)

I have tried the following:

AmazonS3Client s3 = new AmazonS3Client(
    new BasicAWSCredentials(ACCESS_KEY, SECRET_KEY));
s3.createBucket(bucketName + "/" + dirName); //throws exception

which throws an exception on the second line.

A short snippet which creates a sub-directory and uploads files to it will be deeply appreciated.

Upvotes: 37

Views: 66340

Answers (7)

Rajat Goel
Rajat Goel

Reputation: 173

You may use below snippet in JAVA SDK V2:

        PutObjectRequest por = PutObjectRequest.builder()
                .bucket("bucketName")
                .key("dirName")
                .build();
        s3Client.putObject(por, RequestBody.empty());

Note: dirName must end with / to be considered as a folder in S3

Upvotes: 1

Supun Sandaruwan
Supun Sandaruwan

Reputation: 2418

This worked for me. I used spring boot and file uploaded according to Multipart mechanism. I wanted to save my images inside the photos folder in my aws s3 bucket. My need is save like this photos/mypic.jpg

----controller class method----

@PostMapping("/uploadFile")
    public String uploadFile(@RequestPart(value = "file") MultipartFile file) throws IOException {
        return this.amazonClient.uploadFile(file);
}

----service class (Implementation of controller)----

 public String uploadFile(MultipartFile multipartFile) throws IOException {
    
            try {
                File file = convertMultiPartToFile(multipartFile);
                String fileName = "photoes/"+generateFileName(multipartFile);  //here give any folder name you want
                uploadFileTos3bucket(fileName, file);
            } catch (AmazonServiceException ase) {
                logger.info("Caught an AmazonServiceException from GET requests, rejected reasons:");
            }
            return fileName;
        }

The point is concatenate the folder name you want as prefix of the fileName

additionally I will show you how to delete folder. The point is give the folder name as the keyName(key name is uploaded object name in the s3 bucket.). I will show code snippet also.

----controller class method----

@DeleteMapping("/deleteFile")
    public String deleteFile(@RequestPart(value = "keyName") String keyName) {
        return this.amazonClient.deleteFile(keyName);
    }

----service class (Implementation of controller)----

 public String deleteFile(String keyName){
        try {
            s3client.deleteObject(new DeleteObjectRequest(bucketName, keyName));
        } catch (SdkClientException e) {
            e.printStackTrace();
        }
        return "deleted file successfully!";
    }

for delete photos folder that we created , call method like this. deleteFile("photos/") important:- / is mandatory

Upvotes: 0

Bollywood
Bollywood

Reputation: 484

Leaving this answer here just in case someone stumbles upon this. I have been using aws sdk version - 1.11.875 and the following successfully created a folder for me when trying to upload a file into S3 bucket. I did not have to explicitly create the folder as mentioned in the earlier answer.

private void uploadFileToS3Bucket(final String bucketName, final File file) {
    final String fileName = "parent/child/" + file.getName();
    final PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, fileName, file);
    amazonS3.putObject(putObjectRequest);
}

This will create the parent and parent/child folders in the specified S3 bucket and upload the file into child folder.

Upvotes: 1

jalogar
jalogar

Reputation: 1684

In newer versions of the SDK, you can do something like this (no need to create empty InputStream) to create an empty folder:

String key = parentKey + newFolderName;
if (!StringUtils.endsWith(key, "/")) {
    key += "/";
}

PutObjectRequest putRequest = PutObjectRequest.builder()
        .bucket(parent.getBucket())
        .key(key)
        .acl("public-read")
        .build();
s3Client.putObject(putRequest, RequestBody.empty());

Upvotes: 6

Panuf
Panuf

Reputation: 82

if You want to create folder then you need to use put command using following keys to create folder1 in:

in root of bucket -> folder1/folder1_$folder$

in path folder2/folder3/ -> folder2/folder3/folder1/folder1_$folder$

It is always all_previous_folders/folderName/folderName_$folder$

Upvotes: -2

filip_j
filip_j

Reputation: 1225

S3 doesn't see directories in the traditional way we do this on our operating systems. Here is how you can create a directory:

public static void createFolder(String bucketName, String folderName, AmazonS3 client) {
    // create meta-data for your folder and set content-length to 0
    ObjectMetadata metadata = new ObjectMetadata();
    metadata.setContentLength(0);

    // create empty content
    InputStream emptyContent = new ByteArrayInputStream(new byte[0]);

    // create a PutObjectRequest passing the folder name suffixed by /
    PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName,
                folderName + SUFFIX, emptyContent, metadata);

    // send request to S3 to create folder
    client.putObject(putObjectRequest);
}

As casablanca already said you can upload files to directories like this:

s3.putObject("someBucket", "foo/bar1", file1);

Read the whole tutorial here for details, and the most important thing is you will find info how to delete the directories.

Upvotes: 36

casablanca
casablanca

Reputation: 70731

There are no "sub-directories" in S3. There are buckets and there are keys within buckets.

You can emulate traditional directories by using prefix searches. For example, you can store the following keys in a bucket:

foo/bar1
foo/bar2
foo/bar3
blah/baz1
blah/baz2

and then do a prefix search for foo/ and you will get back:

foo/bar1
foo/bar2
foo/bar3

See AmazonS3.listObjects for more details.


Update: Assuming you already have an existing bucket, the key under that bucket would contain the /:

s3.putObject("someBucket", "foo/bar1", file1);
s3.putObject("someBucket", "foo/bar2", file2);
...

Then you can list all keys starting with foo/:

ObjectListing listing = s3.listObjects("someBucket", "foo/");

Upvotes: 57

Related Questions