Search code examples
javaandroidzipfileinputstreamfileoutputstream

How to create a ZIP InputStream in Android without creating a ZIP file first?


I use NanoHTTPD as web server in my Android APP, I hope to compress some files and create a InputStream in server side, and I download the InputStream in client side using Code A.

I have read Code B at How to zip and unzip the files?, but how to create a ZIP InputStream in Android without creating a ZIP file first?

BTW, I don't think Code C is good way, because it make ZIP file first, then convert ZIP file to FileInputStream , I hope to create a ZIP InputStream directly!

Code A

private Response ActionDownloadSingleFile(InputStream fis)    {      
    Response response = null;
    response = newChunkedResponse(Response.Status.OK, "application/octet-stream",fis);
    response.addHeader("Content-Disposition", "attachment; filename="+"my.zip");
    return response;
}

Code B

public static void zip(String[] files, String zipFile) throws IOException {
    BufferedInputStream origin = null;
    ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(zipFile)));
    try { 
        byte data[] = new byte[BUFFER_SIZE];

        for (int i = 0; i < files.length; i++) {
            FileInputStream fi = new FileInputStream(files[i]);    
            origin = new BufferedInputStream(fi, BUFFER_SIZE);
            try {
                ZipEntry entry = new ZipEntry(files[i].substring(files[i].lastIndexOf("/") + 1));
                out.putNextEntry(entry);
                int count;
                while ((count = origin.read(data, 0, BUFFER_SIZE)) != -1) {
                    out.write(data, 0, count);
                }
            }
            finally {
                origin.close();
            }
        }
    }
    finally {
        out.close();
    }
}

Code C

File file= new File("my.zip");
FileInputStream fis = null;
try
{
    fis = new FileInputStream(file);
} catch (FileNotFoundException ex)
{

}

Solution

  • ZipInputStream as per the documentation ZipInputStream

    ZipInputStream is an input stream filter for reading files in the ZIP file format. Includes support for both compressed and uncompressed entries.

    Earlier I answered to this question in a way that it is not possible using ZipInputStream. I am Sorry.

    But after investing some time I found that it is possible as per the below code

    It is very much obvious that since you are sending files in zip format over the network.

    //Create proper background thread pool. Not best but just for solution
    new Thread(new Runnable() {
      @Override
      public void run() {
    
       // Moves the current Thread into the background
       android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND);
    
        HttpURLConnection httpURLConnection = null;
        byte[] buffer = new byte[2048];
        try {
          //Your http connection
          httpURLConnection = (HttpURLConnection) new URL("https://s3-ap-southeast-1.amazonaws.com/uploads-ap.hipchat.com/107225/1251522/SFSCjI8ZRB7FjV9/zvsd.zip").openConnection();
    
          //Change below path to Environment.getExternalStorageDirectory() or something of your
          // own by creating storage utils
          File outputFilePath = new File  ("/mnt/sdcard/Android/data/somedirectory/");
    
          ZipInputStream zipInputStream = new ZipInputStream(new BufferedInputStream(httpURLConnection.getInputStream()));
          ZipEntry zipEntry = zipInputStream.getNextEntry();
    
          int readLength;
    
          while(zipEntry != null){
            File newFile = new File(outputFilePath, zipEntry.getName());
    
            if (!zipEntry.isDirectory()) {
              FileOutputStream fos = new FileOutputStream(newFile);
              while ((readLength = zipInputStream.read(buffer)) > 0) {
                fos.write(buffer, 0, readLength);
              }
              fos.close();
            } else {
              newFile.mkdirs();
            }
    
            Log.i("zip file path = ", newFile.getPath());
            zipInputStream.closeEntry();
            zipEntry = zipInputStream.getNextEntry();
          }
          // Close Stream and disconnect HTTP connection. Move to finally
          zipInputStream.closeEntry();
          zipInputStream.close();
        } catch (IOException e) {
          e.printStackTrace();
        }finally {
          // Close Stream and disconnect HTTP connection.
          if (httpURLConnection != null) {
            httpURLConnection.disconnect();
          }
        }
      }
    }).start();