我正在尝试使用java.net.Socket不带java.net.URL外部库的图像进行下载。这是我所拥有的,我不确定什么不起作用。
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行交换为:
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(...)但这没有用。
ImageIO.read(...)
BufferedReader
这是打印的字符串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标头?)。这个问题与此类似,但是我试图创建一个图像而不是一个文件。
java.awt.image.BufferedImage
javafx.scene.image.Image
使用BufferedReader有误,原因有两个:
String
您需要通过手术来解决此问题,创建一个所需大小的字节缓冲区,并使用an InputStream根据自己的条件逐字节读取流。另外,由于您知道HTTP标头的结尾为“ \ r \ n \ r \ n”(或13 10 13 10字节),因此可以扫描自己的缓冲区以查找此模式并采取相应的措施。
InputStream
最好的选择是将图像下载到文件中,然后使用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();