Search code examples
javaapiresthttpurlconnectionbufferedreader

How do I work with a REST API in Java that returns a zip file?


I am familiar with the basics of making a GET request in Java using the HttpURLConnection class. In a normal situation where the return type would be a JSON, I'd do something like this:

    URL obj = new URL(myURLString);
    HttpURLConnection con = (HttpURLConnection) obj.openConnection();
    con.setRequestMethod("GET");
    int responseCode = con.getResponseCode();
    if (responseCode == HttpURLConnection.HTTP_OK) {
        BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
        String inpLine;
        StringBuffer resp = new StringBuffer();

        while ((inpLine = in.readLine()) != null) {
            resp.append(inputLine);
        }
        in.close();
        System.out.println(resp.toString());                          
    } else { System.out.println("Request failed");

However, the current endpoint I'm trying to work with sends back a zip file containing various types of files. The 'Content-Type' in that case would be 'application/octet-stream'. Hitting that endpoint with the above code results in a mess of symbols (not sure what it's called) written to the console. Even in Postman, I see the same, and it only works when I use the 'Send & Download' option when making the request, which prompts me to save the response and I get the zip file.

Any help on how to hit the API and download the returned zip file through Java? Thank you in advance.

Edit: What I intend to do with the zip file is save it locally and then other parts of my program will work with the contents.


Solution

  • I guess you can try this API:

    try (ZipInputStream zis = new ZipInputStream(con.getInputStream())) {
            
        ZipEntry entry; // kinda self-explained (a file inside zip)
    
        while ((entry = zis.getNextEntry()) != null) {
             // do whatever you need :)
             // this is just a dummy stuff
            System.out.format("File: %s Size: %d Last Modified %s %n",
                        entry.getName(), entry.getSize(),
                        LocalDate.ofEpochDay(entry.getTime() / MILLS_IN_DAY));
        }
    }
    

    In any case, you get a stream, so you can do all the stuff that java IO API allows you to do.

    For instance, to save the file you can do something like:

    // I am skipping here exception handling, closing stream, etc.
    byte[] zipContent = zis.readAllBytes();
    new FileOutputStream("some.zip").write(zipContent);
    

    To do something with files inside zip you can do something like:

     // again, skipping exceptions, closing, etc.
     // also, you'd probably do this in while loop as in the first example
     // so let's say we get ZipEntry 
     ZipEntry entry = zis.getNextEntry();
     
     // crate OutputStream to extract the entry from zip file
     final OutputStream os = new FileOutputStream("c:/someDir/" + entry.getName());
     
     
     byte[] buffer = new byte[1024];
     int length;
     
     //read the entry from zip file and extract it to disk
     while( (length = zis.read(buffer)) > 0) {
         os.write(buffer, 0, length);
     }
    
     // at this point you should get your file
    

    I know, this is kinda low level API, you need to deal with streams, bytes, etc., perhaps there are some libs that allows to do this with a single line of code or something :)