0

I have a web server with a PHP script that gives me a random image stored on the server. This response is directly an image with the following header :

HTTP/1.1 200 OK
Date: Mon, 20 Jan 2020 12:10:05 GMT
Server: Apache/2.4.29 (Ubuntu)
Expires: Mon, 1 Jan 2099 00:00:00 GMT
Last-Modified: Mon, 20 Jan 2020 12:10:05 GMT
Cache-Control: no-store, no-cache, must-revalidate
Cache-Control: post-check=0, pre-check=0
Pragma: no-cache
Content-Length: 971646
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: image/png

As you can see, the server replies directly to me with a MIME png file type. Now I want to retrieve this image from a JAVA program. I already have a code that allows me to read text from an http request but how do I save an image from the web?

public class test {

    // one instance, reuse
    private final HttpClient httpClient = HttpClient.newBuilder()
            .version(HttpClient.Version.HTTP_2)
            .build();

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

        test obj = new test();

        System.out.println("Testing 1 - Send Http POST request");
        obj.sendPost();

    }

    private void sendPost() throws Exception {

        // form parameters
        Map<Object, Object> data = new HashMap<>();
        data.put("arg", "value");

        HttpRequest request = HttpRequest.newBuilder()
                .POST(buildFormDataFromMap(data))
                .uri(URI.create("url_here"))
                .setHeader("User-Agent", "Java 11 HttpClient Bot") // add request header
                .header("Content-Type", "application/x-www-form-urlencoded")
                .build();

        HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());

        // print status code
        System.out.println(response.statusCode());

        // print response body
                System.out.println(response.headers());

                try {
                    saveImage(response.body(), "path/to/file.png");
                }
                catch(IOException e) {
                    e.printStackTrace();
                }
        }

    public static void saveImage(String image, String destinationFile) throws IOException {     
            //What to write here ?
    }

    private static HttpRequest.BodyPublisher buildFormDataFromMap(Map<Object, Object> data) {
        var builder = new StringBuilder();
        for (Map.Entry<Object, Object> entry : data.entrySet()) {
            if (builder.length() > 0) {
                builder.append("&");
            }
            builder.append(URLEncoder.encode(entry.getKey().toString(), StandardCharsets.UTF_8));
            builder.append("=");
            builder.append(URLEncoder.encode(entry.getValue().toString(), StandardCharsets.UTF_8));
                }

        return HttpRequest.BodyPublishers.ofString(builder.toString());
    }

Thank you for your response.

lerwox
  • 3
  • 2
  • Just a 2c, but unless the server is sending the image as a Base64 Encoded string, the easiest approach would be to read the image as an array of bytes, and write that to file. – npinti Jan 20 '20 at 12:19
  • use input stream to download any file type for more refer in this [url](https://stackoverflow.com/questions/18210700/best-method-to-download-image-from-url-in-android) – Nazim ch Jan 20 '20 at 12:32
  • Thank you very much @Nazimch you solved my problem – lerwox Jan 23 '20 at 12:17

2 Answers2

0

try this one:

public static void saveImage(String imageUrl, String destinationFile) throws IOException {

    URL url = new URL(imageUrl);
    try(InputStream is = url.openStream();
    OutputStream os = new FileOutputStream(destinationFile)){

            byte[] b = new byte[2048];
            int length;

            while ((length = is.read(b)) != -1) {
                os.write(b, 0, length);
            }

            }catch(IOException  e){
            throw e;
            }
    }

Getting Image from URL (Java)

pikkuez
  • 310
  • 1
  • 18
Marc Stroebel
  • 2,295
  • 1
  • 12
  • 21
  • I can't use it because I need a POST request with parameters – lerwox Jan 21 '20 at 13:06
  • have a look at https://docs.oracle.com/en/java/javase/11/docs/api/java.net.http/java/net/http/HttpResponse.BodyHandlers.html: `// Receives the response body as an InputStream HttpResponse response = client .send(request, BodyHandlers.ofInputStream());` Then write the stream to a file. – Marc Stroebel Jan 21 '20 at 20:46
  • Thank you very much @MarcStröbel you solved my problem. – lerwox Jan 23 '20 at 12:16
0

I actually wrote my own Http client which is part of an Open-source Java library called MgntUtils, that allows you to read both textual and binary responses. Your code could look as follows:

HttpClient client = new HttpClient();
client.setContentType("application/json; charset=utf-8"); //set any appropriate content type (of the input if you send any information from the client to the server)
client.setRequestProperty("Authorization", "Bearer ey..."); // this is just an example of how to set any header if you need. You might not need to set any additional headers
ByteBuffer buff = client.sendHttpRequestForBinaryResponse("http://example.com/image",HttpMethod.POST, "bla bla"); //This is example of invoking method POST with some input data "bla bla", third parameter is not mandatory if you have no data to pass
ByteBuffer buff1 = client.sendHttpRequestForBinaryResponse("http://example.com/image",HttpMethod.GET); //This is an example of invoking GET method

I and some other people used this library, and it is simple to use and works nicely. The library is available as Maven artifacts here and from GitHub including sources and JavaDoc here JavaDoc for HttpClient class is here

Michael Gantman
  • 7,315
  • 2
  • 19
  • 36