简体   繁体   中英

Java Unzip all files, ignoring directories and upload to S3

My current goal is to take a ZIP file that a user uploads, blow it up take all the files and upload each file to Amazon S3. My current implementation works fine when the files are in the root of the ZIP file. If the ZIP has a folder with more files inside the function fails. Here is the method:

public Result zip() throws IOException {

Http.MultipartFormData body = request().body().asMultipartFormData();
List <Http.MultipartFormData.FilePart> uploadFilePart = body.getFiles();
for(Http.MultipartFormData.FilePart uploadFileParts: uploadFilePart) {

    final File uploadfile = (File) uploadFileParts.getFile();
    ZipFile zipIn = new ZipFile(uploadfile);
    final Enumeration<? extends ZipEntry> entries = zipIn.entries();
    while (entries.hasMoreElements()) {
        final ZipEntry entry = entries.nextElement();
        PutObjectRequest putObjectRequest = new PutObjectRequest(s3Bucket, entry.getName(), new File(entry.getName())); // create upload object to send to S3
        putObjectRequest.withCannedAcl(CannedAccessControlList.Private); // set to private, so only the server can access it
        s3Client.putObject(putObjectRequest); // upload file
    }
    zipIn.close();
}
return ok();

I am using the Play Framework. When I try to upload a ZIP with folders inside, it throws the error:

play.api.http.HttpErrorHandlerExceptions$$anon$1: Execution exception[[SdkClientException: Unable to calculate MD5 hash: test/Selection_010.png (Not a directory)]]

What I'm assuming is happening is the entries.nextElement() is treating the folder 'test' inside the ZIP as a file it self. My goal is not to have any folders in the S3 bucket just the files inside the ZIP regardless if it had sub folders or not.

Is there anyway to pull out the files inside the subfolders of the ZIP so they 'act' like root files of the ZIP and upload them to S3?

Cheers!

Edit:

I've modified the method a bit to:

while (entries.hasMoreElements()) {
final ZipEntry entry = entries.nextElement();
if (!entry.isDirectory()){
    Logger.info(entry.getName());
    PutObjectRequest putObjectRequest = new PutObjectRequest(s3Bucket, entry.getName(), new File(entry.getName())); // create upload object to send to S3
    putObjectRequest.withCannedAcl(CannedAccessControlList.Private); // set to private, so only the server can access it
    s3Client.putObject(putObjectRequest); // upload file

The Zip file I'm trying to upload has the structure:

  • Workspace 1_005.png
  • Selection_009.png
  • test/maxresdefault.jpg
  • test/191559.jpg

Where 'test' is a sub-folder in the Zip. If I just print out the zip I get:

play.api.Play - Application started (Dev) application - Selection_009.png
application - Workspace 1_005.png
application - test/maxresdefault.jpg
application - test/191559.jpg

If it tries to upload it throws the error:

play.api.http.HttpErrorHandlerExceptions$$anon$1: Execution exception[[SdkClientException: Unable to calculate MD5 hash: test/maxresdefault.jpg (Not a directory)]]
Caused by: com.amazonaws.SdkClientException: Unable to calculate MD5 hash: test/maxresdefault.jpg (Not a directory)
Caused by: java.io.FileNotFoundException: test/maxresdefault.jpg (Not a directory)

I'm wondering if it's not picking up the correct path of the file or something else it going on? Any help is appreciated. Thanks!

Something like this?

 File[] files = new File("").listFiles();
 uploadFiles(files);


 public static void uploadFiles(File[] files) {
    for (File file : files) {
    if (file.isDirectory()) {
        uploadFiles(file.listFiles()); // Calls same method again.
    } else {
        // do the uploading
    }
}

This would iterate through ignoring the directories, not sure if it is the most efficient way though.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM