如何使用Java的Socket从远程HTTP服务器下载一个图像?(How to download a

2019-10-21 07:05发布

我一直在试图实现使用Java Socket实现简单的HTTP客户端。 在我的计划,我从服务器请求的图像,并试图请求的JPEG图像复制本地机器上。 我已成功地构建了请求和接收到的期望的内容。 我还分离出的响应报头和内容。 但问题是,当我写的使用字节FileOutputStream为.jpeg文件,写打开的图像浏览器(例如Picasa)文件时,图像似乎无效后。 这是我的全部代码。 任何人都可以PLZ告诉我,什么是错的代码? 为什么像无效?

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

import sun.misc.IOUtils;


public class ImageCopy {
   public static void main(String args[]) throws IOException{
               String host = "www.uni-koblenz-landau.de";   //declare the host name
               String resourceLoc = "/images/starts-c-ko.jpg"; //declare the specific pagename of get
               HttpRequester req = new HttpRequester();
               req.request(host, resourceLoc); //send the request mentiong the host and pagename


   }
  }

class HttpRequester{
    public void request(String host, String resourceLoc) throws IOException{
         Socket httpSocket = new Socket(host, 80); //create the request for port 80
         PrintWriter writer = new PrintWriter(httpSocket.getOutputStream());
         FileOutputStream foutStream = new FileOutputStream("E:\\quora.jpeg"); //creating file to hold the output stream

         // building the header fields
        String protocol = "GET /" +resourceLoc+" HTTP/1.1";
        String connection ="Connection: close";
        String acceptedLanguage ="Accept-Language: de,en;q=0.7,en-us;q=0.3";
        String headerEnd = "";
        String HostHeader = "Host: www.uni-koblenz-landau.de";

        // writing the headers to the outputstream

       writer.println(protocol);
       writer.println(HostHeader);
       writer.println(connection);
       writer.println(acceptedLanguage);
       writer.println(headerEnd);

       writer.flush();

      // request sent

       BufferedInputStream reader = new BufferedInputStream(httpSocket.getInputStream());

       InputStream is;

       int byteCode =0;
       char ch ;
           StringBuilder builder = new StringBuilder();

       while((byteCode=reader.read())!=-1)
       {
           builder.append((char)byteCode);
          // System.out.print((char)byteCode);

       }

       String text = builder.toString();
       // sub[0] is supposed to contain the header and sub[1] should contain the bytes of the           image

       String[] sub = text.split("\r\n\r\n");
       System.out.println(sub[0]);

       byte[] byts = sub[1].getBytes();

       for(int i=0;i<byts.length;i++){
           foutStream.write(byteCode);
       }
       System.out.println(byts.length);
    }

}  

Answer 1:

请您先试试这个工作代码:

import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;

public class URLTest {

  private static void sendGet() throws Exception {

    String url = "http://www.uni-koblenz-landau.de/images/starts-c-ko.jpg";

    URL obj = new URL(url);
    HttpURLConnection con = (HttpURLConnection) obj.openConnection();

    // optional default is GET
    con.setRequestMethod("GET");

    //add request header
    con.setRequestProperty("User-Agent", "Mozilla/5.0");

    int responseCode = con.getResponseCode();
    System.out.println("\nSending 'GET' request to URL : " + url);
    System.out.println("Response Code : " + responseCode);

    InputStream in = con.getInputStream();
    OutputStream out = new FileOutputStream("/Users/ravikiran/Desktop/abc.jpg");
    try {
      byte[] bytes = new byte[2048];
      int length;

      while ((length = in.read(bytes)) != -1) {
        out.write(bytes, 0, length);
      }
    } finally {
      in.close();
      out.close();
    }
  }

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


Answer 2:

有所示代码中的至少2个问题。 首先是微不足道的,靠近你有计划的结尾:

   byte[] byts = sub[1].getBytes();

   for(int i=0;i<byts.length;i++){
       foutStream.write(byteCode);
   }

我认为foutStream.write(byts[i]); 应该会更好。

二是更加微妙。 你得到的字节,并将其转换为char的字符串生成器,然后让他们回来为字节。 如预期的字节值> = 128不工作。

我只是做了这个小测试:

public class ByteCharTest {
    @Test
    public void test1() {
        byte[] bytes = new byte[]{ 'x', (byte) 0xc3, (byte) 0xa9,
            (byte) 0xc3, (byte) 0xa8, 'y', (byte) 0xe9, (byte) 0xe8, 'z'};
        StringBuilder sb = new StringBuilder();
        for(byte b: bytes) {
            sb.append((char) b);
        }
        String s = sb.toString();
        byte[] byte2 = s.getBytes();
        assertEquals(bytes.length, byte2.length);
        for(int i=0; i<bytes.length; i++) {
            assertEquals(bytes[i], byte2[i]);
        }
    }
}

而且它打破。 下的调试器,字符串s为“x \ uffce \ uffa9 \ uffc3 \ uffa9y \ uffe9 \ uffe8z”,因为从字节转换为CHAR传播符号位和字节2是x????y??z

测试工作,如果StringBuilder与反馈:

            sb.append((char) (((int) b) && 0xff));

因此,在你的代码,你应该有:

   while((byteCode=reader.read())!=-1)
   {
       builder.append((char) (((int) byteCode) && 0xff));
      // System.out.print((char)byteCode);
   }

只是为了解释测试的字节, 0xc3 0xa90xc3 0xa8是UTF-8编码éè0xe8 0xe9针对Latin1的代码éè ...



Answer 3:

实际上适合你的问题解决方案:

// Initialize the stream.
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)
        foutStream.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;
                foutputStream.write(bytes, i+4, 2048-i-4);
                break;
            }
        }
    }
}
inputStream.close();
foutStream.close();


文章来源: How to download an image using Java Socket from a remote Http server?