如何使用Java套接字HTTP / 1.1请求下载图像? [英] How to download an image with a Java socket HTTP/1.1 request?

查看:112
本文介绍了如何使用Java套接字HTTP / 1.1请求下载图像?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 java.net.Socket 下载图像而不使用 java.net.URL 和外部库。这是我的,我不确定什么不起作用。

I am trying to download images using java.net.Socket without java.net.URL and external libraries. Here is what I have and I am not sure what isn't working.

        String domain = "www.manchester.edu";
        String path = "/images/default-source/default-album/slide1.jpg";
        Socket socket = new Socket(domain,80);

        PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())));
        out.println("" +
                "Get "+path+" HTTP/1.1\n" +
                "Host: "+domain+"\n"+
                "");
        out.println();
        out.flush();

        BufferedImage image = ImageIO.read(socket.getInputStream());

为了查看流中的内容,请交换 BufferedImage line for:

In order to see what is coming through the stream, exchange the BufferedImage line for:

    BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
    String inputLine;
    while ((inputLine = in.readLine()) != null && inputLine.trim() != "0") {
       System.out.println(inputLine);
    }

大概是 ImageIO.read(...) 方法不期望套接字输入流中的HTTP头。但我不知道如何删除标题。我尝试用 BufferedReader 读取标题行,然后将套接字输入流传递给 ImageIO.read(...)但是没有用。

Presumably the ImageIO.read(...) method does not expect the HTTP header in the socket input stream. But I am not sure how to remove the header. I've tried reading the header lines with BufferedReader and then passing the socket input stream to ImageIO.read(...) but that did not work.

这是由 BufferedReader 打印的字符串:

HTTP/1.1 200 OK
Cache-Control: public, max-age=7776000
Content-Length: 96876
Content-Type: image/jpeg
Expires: Thu, 04 Feb 2016 21:36:46 GMT
Last-Modified: Tue, 15 Sep 2015 14:23:40 GMT
Server: Microsoft-IIS/8.5
content-disposition: inline; filename=slide1.jpg
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Fri, 06 Nov 2015 21:36:46 GMT

����...

最后的不可打印字符似乎表明标题后面的内容是某种形象。但是如何将其转换为 java.awt.image.BufferedImage javafx.scene.image.Image ?后者有一个构造函数,它接受一个输入流,我尝试过,但它不起作用(因为http标题?)。这个问题类似于这个,但我试图创建一个图像而不是文件。

The non-printable characters at the end seems to indicate that what follows the header is an image of some sort. But how can I turn this into a java.awt.image.BufferedImage or a javafx.scene.image.Image? The latter has a constructor that takes an input stream, and I've tried that, but it doesn't work (because of the http header?). This question is similar to this one, but I am trying to create an image not a file.

推荐答案

使用 BufferedReader 是错误的,原因有两个:

Using BufferedReader is a mistake for 2 reasons:


  1. 它将字节转换为 String 然后将其转换回字节以将其发送到输出流。转换可能(并且可能会)导致数据丢失;

  2. 它解析了太多字节而你无法控制它。

  1. It converts bytes to a String which you then convert back into bytes to send it into the output stream. The conversions may (and probably will) lead to loss of data;
  2. It parses too many bytes and you have no control over it.

你需要手术接近,创建一个所需大小的字节缓冲区,并使用 InputStream 来读取流字节按您自己的条件逐字节。此外,由于您知道HTTP标头结尾是\\\\\\\ n(或13 10 13 10字节),您可以扫描自己的缓冲区以获取此模式并采取相应措施。

You need to approach this surgically, creating a buffer of bytes of the size you want and using an InputStream to read the stream byte-by-byte on your own terms. Also, since you know that the HTTP header ending is "\r\n\r\n" (or 13 10 13 10 in bytes), you can scan your own buffer for this pattern and act accordingly.

最好的办法是将图像下载到文件中,然后使用ImageIO从本地文件中读取图像。

Your best bet is to download the image to a file and then use the ImageIO to read it from the local file.

    // Initialize the streams.
    final FileOutputStream fileOutputStream = new FileOutputStream(file);
    final InputStream inputStream = socket.getInputStream();

    // Header end flag.
    boolean headerEnded = false;

    byte[] bytes = new byte[2048];
    int length;
    while ((length = inputStream.read(bytes)) != -1) {
        // If the end of the header had already been reached, write the bytes to the file as normal.
        if (headerEnded)
            fileOutputStream.write(bytes, 0, length);

        // This locates the end of the header by comparing the current byte as well as the next 3 bytes
        // with the HTTP header end "\r\n\r\n" (which in integer representation would be 13 10 13 10).
        // If the end of the header is reached, the flag is set to true and the remaining data in the
        // currently buffered byte array is written into the file.
        else {
            for (int i = 0; i < 2045; i++) {
                if (bytes[i] == 13 && bytes[i + 1] == 10 && bytes[i + 2] == 13 && bytes[i + 3] == 10) {
                    headerEnded = true;
                    fileOutputStream.write(bytes, i+4 , 2048-i-4);
                    break;
                }
            }
        }
    }
    inputStream.close();
    fileOutputStream.close();

这篇关于如何使用Java套接字HTTP / 1.1请求下载图像?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆