How to download a file via HTTP GET and HTTP POST in Java without using any external libraries

Apart from uploading a file to a HTTP server endpoint, another common task for a Java HTTP client is to download a file from a HTTP server. Even though there are many Java external libraries to help us do so, using the facilities in the Java standard runtime installation is not difficult. Furthermore, we will be able to keep our Java application leaner if we can download files without additional dependencies.

In case you need a reference, this is how to download a file via HTTP GET and HTTP POST in Java without using any external libraries.

Downloading a file from a HTTP server endpoint via HTTP GET

Generally, downloading a file from a HTTP server endpoint via HTTP GET consists of the following steps:

  • Construct the HTTP GET request to send to the HTTP server.
  • Send the HTTP request and receive the HTTP Response from the HTTP server.
  • Save the contents of the file from HTTP Response to a local file.

Java codes to download a file from a HTTP server endpoint via HTTP GET

Given these points, let us modify the codes from how to send a HTTP GET request in Java to save the contents of the file from a HTTP Response to a local file:

import java.io.IOException;
import java.io.FileOutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.ReadableByteChannel;

public class HttpGetDownloadFileExample {

    public static void main(String[] args) {

        ReadableByteChannel readableChannelForHttpResponseBody = null;
        FileChannel fileChannelForDownloadedFile = null;

        try {
            // Define server endpoint
            URL robotsUrl = new URL("http://www.techcoil.com/robots.txt");
            HttpURLConnection urlConnection = (HttpURLConnection) robotsUrl.openConnection();

            // Get a readable channel from url connection
            readableChannelForHttpResponseBody = Channels.newChannel(urlConnection.getInputStream());

            // Create the file channel to save file
            FileOutputStream fosForDownloadedFile = new FileOutputStream("robots.txt");
            fileChannelForDownloadedFile = fosForDownloadedFile.getChannel();

            // Save the body of the HTTP response to local file
            fileChannelForDownloadedFile.transferFrom(readableChannelForHttpResponseBody, 0, Long.MAX_VALUE);

        } catch (IOException ioException) {
            System.out.println("IOException occurred while contacting server.");
        } finally {

            if (readableChannelForHttpResponseBody != null) {

                try {
                    readableChannelForHttpResponseBody.close();
                } catch (IOException ioe) {
                    System.out.println("Error while closing response body channel");
                }
            }

            if (fileChannelForDownloadedFile != null) {

                try {
                    fileChannelForDownloadedFile.close();
                } catch (IOException ioe) {
                    System.out.println("Error while closing file channel for downloaded file");
                }
            }

        }
    }
}

As shown above, we had created a class with a main method. When the main method is executed, our Java program does several things.

Firstly, we had declared an instance of ReadableByteChannel and an instance of FileChannel to contain null values so as to facilitate closure in the finally block.

After we had done so, we define a try block for running the file download logic that may throw checked exceptions.

Within the try block, we first use an instance of URL to get an instance of HttpURLConnection that points to a HTTP server endpoint for the file that we wish to download.

Once we have done so, we get an instance of ReadableByteChannel that is mapped to the input stream of urlConnection. In addition, we set it to the readableChannelForHttpResponseBody variable for manipulation later.

After we had an instance of ReadableByteChannel, we then proceed to get a FileChannel that will point to a local file path where we want to save the downloaded file. In this case, we want to save the downloaded file as robots.txt in the same directory where we run our Java program.

Finally, we use fileChannelForDownloadedFile.transferFrom method on readableChannelForHttpResponseBody to save the contents of the HTTP response body to the local file.

Downloading a file from a HTTP server endpoint via HTTP POST

There can be cases where the client need to supply some information to the HTTP server in order to download a file. In such a situation, HTTP POST is a more appropriate HTTP method to use for downloading the file.

As with HTTP GET, downloading of a file from the HTTP server via HTTP POST consists of the following steps:

  • Construct the HTTP POST request to send to the HTTP server.
  • Send the HTTP request and receive the HTTP Response from the HTTP server.
  • Save the contents of the file from HTTP Response to a local file.

Java codes to download a file from a HTTP server endpoint via HTTP POST

Given these points, let's modify the Java code from how to send a HTTP POST request in Java to save the contents of the file from a HTTP Response to a local file:

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.ReadableByteChannel;

public class HTTPPostDownloadFileExample {

    public static void main(String[] args) throws IOException {

        // Define the server endpoint to send the HTTP request to
        URL serverUrl =
                new URL("https://www.techcoil.com/process/proof-of-concepts/userNameAndLuckyNumberTextFileGeneration");
        HttpURLConnection urlConnection = (HttpURLConnection)serverUrl.openConnection();

        // Indicate that we want to write to the HTTP request body
        urlConnection.setDoOutput(true);
        urlConnection.setRequestMethod("POST");

        // Writing the post data to the HTTP request body
        BufferedWriter httpRequestBodyWriter =
                new BufferedWriter(new OutputStreamWriter(urlConnection.getOutputStream()));
        httpRequestBodyWriter.write("visitorName=Johnny+Jacobs&luckyNumber=1234");
        httpRequestBodyWriter.close();

        // Get a readable channel from url connection
        ReadableByteChannel readableChannelForHttpResponseBody = Channels.newChannel(urlConnection.getInputStream());

        // Create the file channel to save file
        FileOutputStream fosForDownloadedFile = new FileOutputStream("luckyNumber.txt");
        FileChannel fileChannelForDownloadedFile = fosForDownloadedFile.getChannel();

        // Save the contents of HTTP response to local file
        fileChannelForDownloadedFile.transferFrom(readableChannelForHttpResponseBody, 0, Long.MAX_VALUE);
    }
}

As shown above, we had created a class with a main method which will propagate any occurrences of IOException back to the caller. When the main method is executed, our Java program does several things.

First, it creates an instance of HttpURLConnection, urlConnection, that maps to the HTTP server endpoint at https://www.techcoil.com/process/proof-of-concepts/userNameAndLuckyNumberTextFileGeneration. Given that, we then configure urlConnection to allow us to write to the HTTP request body via urlConnection.setDoOutput(true). After that, we set the HTTP method of the HTTP request as POST via urlConnection.setRequestMethod("POST").

Next, we use an instance of BufferedWriter to write some POST variables to the HTTP request body.

Once we had written the POST variables, we then get an instance of ReadableByteChannel from the input stream of urlConnection. Given that instance, we will then be able to read from the body of the HTTP response.

After we had an instance of ReadableByteChannel, we then proceed to get an instance of FileChannel that will point to a local file path where we want to save the downloaded file. In this case, we will save the downloaded file as luckyNumber.txt in the same directory where we run our Java program.

Finally, we use fileChannelForDownloadedFile.transferFrom on readableChannelForHttpResponseBody to save the contents of the HTTP response body to the local file.

About Clivant

Clivant a.k.a Chai Heng enjoys composing software and building systems to serve people. He owns techcoil.com and hopes that whatever he had written and built so far had benefited people. All views expressed belongs to him and are not representative of the company that he works/worked for.