Friday, October 5, 2018

Java HttpURLConnection | HttpsURLConnection > Implement Pause / Resume in File Downloading > How to Extract Chunked Data When Using HttpURLConnection > Download File as Chunk

It's very important (as well as beneficial) if we can pause / resume our download specially when downloading big file.
Below is a code snippet to download data chunk by chunk. So you can now pause / resume your download whenever you want.
package com.pkm;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.List;
import java.util.Map;

public class JavaChunkDataDownload {
    public static enum Method {
        GET, POST, PUT, PATCH, DELETE
    }

    public static enum Type {
        XML, JSON, URL_ENCODED;
    };

    private static String fileName = "file2.zip";

    public static void main(String[] args) throws Exception {
        String URI = "http://ipv4.download.thinkbroadband.com/100MB.zip?t=" + System.currentTimeMillis();
        //URI = "http://localhost/ForDownload.zip?t=" + System.currentTimeMillis();
        Response response = execute(URI, Method.GET, "", Type.URL_ENCODED);
        println("Get_Result:\n" + lengthString(response.toString().replace("\n", ""), 400) + "...");
    }

    public static Response execute(String url, Method method, String data, Type type) {
        return execute(url, method, data, type, null, null);
    }

    private static Response execute(String requestURL, Method requestMethod, String requestData, Type dataType, Map headers, Integer timeOutMilli) {
        Long started = System.currentTimeMillis();
        String httpResponse = "", responseMessage = "";
        Integer httpCode = 0;
        timeOutMilli = timeOutMilli == null ? 1000 * 30 : timeOutMilli; /* Default read & write timeout */

        HttpURLConnection connection = null;
        try {
            String contentType = "", accept = "", contentLength = "" + requestData.length();
            switch (dataType) {
                case XML:
                    contentType = "text/xml; charset=utf-8";
                    accept = "text/xml";
                    break;
                case JSON:
                    contentType = "application/json";
                    break;
                case URL_ENCODED:
                    contentType = "application/x-www-form-urlencoded";
                    break;
            }

            connection = (HttpURLConnection) new URL(requestURL).openConnection();
            connection.setRequestMethod(requestMethod.name());
            connection.setConnectTimeout(timeOutMilli);
            connection.setReadTimeout(timeOutMilli);
            connection.setRequestProperty("Pragma", "no-cache");
            connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36");

            File outputFileCache = new File(fileName);
            if (outputFileCache.exists()) {
                connection.setAllowUserInteraction(true);
                connection.setRequestProperty("Range", "bytes=" + outputFileCache.length() + "-");
            }

            if (headers != null && headers.size() > 0) {
                for (Object name : headers.keySet().toArray()) {
                    connection.setRequestProperty(name.toString(), headers.get(name.toString()).toString());
                }
            }

            if (requestData.length() > 0) {
                connection.setDoInput(true);
                connection.setDoOutput(true);

                if (accept.length() > 0) {
                    connection.setRequestProperty("Accept", accept);
                }
                if (contentType.length() > 0) {
                    connection.setRequestProperty("Content-Type", contentType);
                }

                connection.setRequestProperty("Content_length", contentLength);
                OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream(), "UTF-8");
                writer.write(requestData);
                writer.flush();
                writer.close();
            }

            httpCode = connection.getResponseCode();
            Boolean validResponse = httpCode >= 200 && httpCode <= 299;
            responseMessage = connection.getResponseMessage();
            String responseContentType = connection.getContentType();
            if (responseContentType == null || responseContentType.length() == 0) {
                responseContentType = "txt";
            }
            else {
                if (responseContentType.contains(";")) {
                    responseContentType = responseContentType.substring(0, responseContentType.indexOf(";"));
                }
                if (responseContentType.contains("text/html")) {
                    responseContentType = "html";
                }
                else if (responseContentType.contains("image/")) {
                    responseContentType = "image";
                }
                else if (responseContentType.contains("/")) {
                    String[] parts = responseContentType.split("/");
                    responseContentType = parts[parts.length - 1];
                }
            }
            Map<String, List<String>> map = connection.getHeaderFields();
            for (Map.Entry<String, List<String>> entry : map.entrySet()) {
                System.out.println("Key : " + entry.getKey() + " ,Value : " + entry.getValue());
            }

            if (validResponse) {
                Long downloadedSize = 0L;
                String connectionField = connection.getHeaderField("content-range");
                if (connectionField != null) {
                    String[] connectionRanges = connectionField.substring("bytes=".length()).split("-");
                    downloadedSize = Long.valueOf(connectionRanges[0]);
                }
                if (connectionField == null && outputFileCache.exists()) {
                    outputFileCache.delete();
                }
                outputFileCache = new File(fileName);
                if (!outputFileCache.exists()) {
                    outputFileCache.createNewFile();
                    outputFileCache.setExecutable(true);
                }
                Long fileLength = connection.getContentLength() + downloadedSize;
                RandomAccessFile output = new RandomAccessFile(outputFileCache, "rw");
                output.seek(downloadedSize);

                InputStream is = connection.getInputStream();
                BufferedInputStream input = new BufferedInputStream(is);

                int readSize = 1024;
                byte data[] = new byte[readSize];
                int count = 0;
                int progress = 0;
                Integer pauseAt = 180;

                Long timeNeeded = System.currentTimeMillis();
                while ((count = input.read(data, 0, readSize)) >= 0 && progress != 100)
                {
                    downloadedSize += count;
                    output.write(data, 0, count);
                    progress = (int) ((downloadedSize * 100) / fileLength);
                    Long mb = output.length() / (1024 * 1024);
                    System.out.println("PROGRESS = " + (progress) + "%, DOWNLOADED=" + mb + " MB, TYPE=" + responseContentType);
                    if (progress >= pauseAt) {
                        break;
                    }
                }
                output.close();
                input.close();

                timeNeeded = (System.currentTimeMillis() - timeNeeded) / 1000;
                System.out.println("TIME REQUIRED=" + timeNeeded);
            }
        }
        catch (Exception ex) {
            httpResponse = "";
            responseMessage = ex.getMessage();
        }
        finally {
            try {
                connection.disconnect();
            }
            catch (Exception ex10) {
            }
        }

        return new Response(requestURL, httpCode, responseMessage, httpResponse, (System.currentTimeMillis() - started));
    }

    public static class Response {
        private String url;
        private Integer code;
        private String message;
        private String body;
        private Long time;

        public Response(String url, Integer code, String message, String body, Long time) {
            this.url = url;
            this.code = code;
            this.message = message;
            this.body = body;
            this.time = time;
        }

        @Override
        public String toString() {
            return "{URL=" + this.url + ",Code=" + this.code + ", Message=" + this.message + ", Time=" + this.time + " Millis, Body=" + this.body + "}";
        }

        public Integer getCode() {
            return this.code;
        }

        public String getMessage() {
            return this.message;
        }

        public String getBody() {
            return this.body;
        }

        public Long getTime() {
            return this.time;
        }
    }

    public static void println(Object o) {
        System.out.println("" + o);
    }

    public static String lengthString(String s, Integer m) {
        return s.length() > m ? s.substring(0, m) : s;
    }
}

No comments:

Post a Comment