如何从远程Http服务器使用Java Socket下载映像?

时间:2014-11-19 09:57:50

标签: java sockets http jpeg

我一直在尝试使用Java Socket实现一个简单的http客户端。在我的程序中,我从服务器请求图像并尝试在本地计算机上复制请求的JPEG图像。我已设法构建请求并收到所需的内容。我还将响应头和内容分开了。但问题是当我使用FileOutputStream将字节写入.jpeg文件时,在写入图像查看器(如picasa)中打开文件后,图像似乎无效。 这是我的整个代码。 任何人都可以告诉我代码有什么问题吗?为什么图像无效?

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

}  

3 个答案:

答案 0 :(得分: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();
  }
}

答案 1 :(得分:0)

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

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

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

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

第二个更微妙。你得到字节,在字符串构建器中将它们转换为char,然后将它们作为字节返回。对于字节值&gt; = 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是&#34; x \ uffce \ uffa9 \ uffc3 \ uffa9y \ uffe9 \ uffe8z&#34;因为从byte到char传播的符号位和byte2的转换是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代码...

答案 2 :(得分:-1)

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

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