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

编程入门 行业动态 更新时间:2024-10-28 16:16:40
如何使用Java套接字HTTP / 1.1请求下载图像?(How to download an image with a Java socket HTTP/1.1 request?)

我试图使用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 ����...

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

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

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); }

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.

Here is the string printed by 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 ����...

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是一个错误,有两个原因:

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

您需要通过手术进行处理,创建所需大小的字节缓冲区,并使用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();

Using BufferedReader is a mistake for 2 reasons:

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; It parses too many bytes and you have no control over it.

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.

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

Here's the code that will allow you to download an Image file (or any other file) by cutting out the header:

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

更多推荐

本文发布于:2023-07-28 23:38:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1310246.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:如何使用   图像   HTTP   Java   request

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!