Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Download multiple files in parallel to a zip-file from S3 using Java

I'd like to download multiple files from some external source like S3, create a single zip file containing all those files and present the user a link to download that zip file.

Obviously I can process the files sequentially, reading the input stream of each one and writing it to ZipOutputStream.

How can I read all the input file streams in parallel and write to a single output stream so that I can present a download link to the user without making them wait until zip file is fully written?

My current code:

String realpath = getServletContext().getRealPath("/");
response.setContentType("application/zip");

response.setHeader("Content-Disposition","attachment; filename="+fi.replace('/', '-')+"_"+ff.replace('/', '-')+".zip");

ServletOutputStream out = null;
ZipOutputStream zipfile = null;

try
{
    List<Object[]> cfdis = /*my hibernate criteria source, your Database?*/
    out = response.getOutputStream();
    zipfile = new ZipOutputStream(out);
    ZipEntry zipentry = null;
    for(Object[] cfdi:cfdis)
    {
        zipentry = new ZipEntry(cfdi[1].toString()+".xml");
        zipfile.putNextEntry(zipentry);
        InputStream in = new FileInputStream(new File(realpath+cfdi[0].toString()));
        byte[] bytes = new byte[FILEBUFFERSIZE];
        int bytesRead;
        while ((bytesRead = in.read(bytes)) != -1)
        {
            zipfile.write(bytes, 0, bytesRead);
        }
    }
like image 240
Muhammad ismail Avatar asked Oct 26 '15 20:10

Muhammad ismail


People also ask

How do I download multiple files from aws S3?

If you have Visual Studio with the AWS Explorer extension installed, you can also browse to Amazon S3 (step 1), select your bucket (step 2), select al the files you want to download (step 3) and right click to download them all (step 4).

How do I move files from one S3 bucket to another in Java?

You can copy an object from one bucket to another by using the AmazonS3 client's copyObject method. It takes the name of the bucket to copy from, the object to copy, and the destination bucket name. s3. copyObject(from_bucket, object_key, to_bucket, object_key); } catch (AmazonServiceException e) { System.

How do I zip multiple files in spring boot?

While downloading multiple files, we can create a zip file in spring boot and download that zip file alone rather then downloading multiple files individually. For this purpose, we first need to create a zip file in spring boot and then set the content type as application/zip to download the zip file.


1 Answers

Read stream for very first file & start writing it to outputstream

protected void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {

    ServletOutputStream sos = response.getOutputStream();
    ZipOutputStream zos = new ZipOutputStream(sos);

    try {
        S3ServiceWrapper s3Service = new S3ServiceWrapper();
        ZipEntry zipentry = null;
        byte bytes[] = new byte[4096];
        response.setContentType("application/zip");
        response.setHeader("Content-Disposition", "attachment; filename=java-s3-download.ZIP");

        for (String objectKey : objectKeys) {
            String name = objectKey.substring(objectKey.lastIndexOf("/"), objectKey.length());
            log.info("Start Writing File::" + name);

            zipentry = new ZipEntry(name);
            zos.putNextEntry(zipentry);
            InputStream in = s3Service.downloadFileAsStream(bucketName, objectKey);
            int bytesRead = -1;

            while ((bytesRead = in.read(bytes)) != -1) {
                zos.write(bytes, 0, bytesRead);
            }

            log.info("Finsih Writing File::" + name);
            in.close();
        }
    } catch (Exception e)

    {
        e.printStackTrace();
    } finally {
        zos.flush();
        zos.closeEntry();
        zos.close();
        sos.close();
    }

}

public InputStream downloadFileAsStream(String bucketName, String objectKey) {
    if (s3Service == null) {
        return null;
    }

    try {
        GetObjectRequest s3ObjectReq = new GetObjectRequest(bucketName, objectKey);
        log.info("Downloading file having key = " + objectKey);
        long startTime=System.currentTimeMillis();
        S3Object downlodedObjectMD = s3Service.getObject(s3ObjectReq);
        log.info("Time to load Stream is "+(System.currentTimeMillis()-startTime)+" ms");
        return downlodedObjectMD.getObjectContent();

    } catch (Exception e) {
        log.error("EXCEPTION = " + e.getMessage(), e);
    }
    return null;
}
like image 186
Muhammad ismail Avatar answered Oct 01 '22 23:10

Muhammad ismail