当前位置: 首页 > 面试题库 >

如何使用Java套接字HTTP / 1.1请求下载图像?

咸星波
2023-03-14
问题内容

我正在尝试使用java.net.Socket不带java.net.URL外部库的图像进行下载。这是我所拥有的,我不确定什么不起作用。

        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行交换为:

    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(...)但这没有用。

这是打印的字符串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

����...

末尾的不可打印字符似乎表明标题之后是某种图像。但是如何将其转换为a java.awt.image.BufferedImage或a
javafx.scene.image.Image?后者有一个接受输入流的构造函数,我已经尝试过了,但是它不起作用(因为http标头?)。这个问题与此类似,但是我试图创建一个图像而不是一个文件。


问题答案:

使用BufferedReader有误,原因有两个:

  1. 它将字节转换为String,然后再转换回字节以将其发送到输出流。转换可能(可能会)导致数据丢失;
  2. 它解析了太多字节,您无法控制它。

您需要通过手术来解决此问题,创建一个所需大小的字节缓冲区,并使用an
InputStream根据自己的条件逐字节读取流。另外,由于您知道HTTP标头的结尾为“ \ r \ n \ r \ n”(或13 10 13
10字节),因此可以扫描自己的缓冲区以查找此模式并采取相应的措施。

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

    // 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();


 类似资料:
  • 我试图下载和保存图像从网络使用python的模块。 以下是我使用的(工作)代码: 以下是使用

  • 问题内容: 我正在尝试使用的模块从网络下载并保存图像。 这是我使用的(工作)代码: 你能帮助我从响应中使用什么属性吗? 问题答案: 你可以使用对象,也可以遍历响应。 默认情况下,使用类似文件的对象不会解码压缩的响应(使用GZIP或deflate)。你可以通过将属性设置为True(requests将其设置False为控制自身解码)来强制为你解压缩。然后,你可以使用将数据流式传输到文件对象: 要遍历响

  • 问题内容: 假设我有一个Java程序,该程序使用HTTP 1.1在服务器上发出HTTP请求,并且不关闭连接。我提出一个请求,并读取从绑定到套接字的输入流返回的所有数据。但是,在发出第二个请求时,服务器没有响应(或者流有问题- 它不再提供任何输入)。如果我按顺序发出请求(请求,请求,读取),则可以正常工作,但(请求,读取,请求,读取)则不能。 有人能解释为什么会发生这种情况吗?(代码片段如下)。无论

  • 问题内容: 我希望能够构造一个原始的HTTP请求并使用套接字发送它。显然,您希望我使用urllib和urllib2之类的东西,但我不想使用它。 它必须看起来像这样: 显然,您还必须请求页面/文件并获取和发布参数 问题答案: 您需要了解的大多数内容都在HTTP / 1.1规范中,如果您想推广自己的HTTP实现,则应该进行以下研究:http : //www.w3.org/Protocols/rfc26

  • 问题内容: 在实现代理服务器时,我将HTTP请求作为字符串发送,如下所示: GET http:// localhost:54321 / x HTTP / 1.1 主机:localhost:54321 缓存控制:无缓存 是否有内置的类来解析此请求? 问题答案: 我对这种解析的内置支持一无所知。如果您确实需要这样的解析器,则可以签出以下库: http //hc.apache.org/index.htm