3

I am trying to download an image from a server through sockets. My code works fine, but when I download the image, the size is correct but the image does not open. I don't know what am I doing wrong. Any suggestion? Thank you

     Socket socket = new Socket(servername, 80);
     DataOutputStream bw = new DataOutputStream(new DataOutputStream(socket.getOutputStream()));
    bw.writeBytes("GET "+filename+" HTTP/1.1\n");
    bw.writeBytes("Host: "+servername+":80\n\n");

    DataInputStream in = new DataInputStream(socket.getInputStream());


    OutputStream dos = new FileOutputStream("testtttt.jpg");
    int count;
    byte[] buffer = new byte[2048];
    while ((count = in.read(buffer)) != -1)
    {
      dos.write(buffer, 0, count);
      dos.flush();
    }
    dos.close();
    System.out.println("image transfer done");

    socket.close();     
   }
user2993368
  • 33
  • 1
  • 3
  • Are you sure the image is a JPG and not a PNG? Also you might try removing the double wrapping of the DataOutputStream. – ug_ Nov 14 '13 at 18:28
  • Thank you for the reply. Yes I am sure the picture is in JPG, I removed the double wrapping of the DataOutputStream but still it gives me just the picture and the size. It does not open – user2993368 Nov 14 '13 at 18:33
  • Don't flush inside the loop. If you're not using a buffered stream it does nothing, and if you are it completely defeats the purpose. There's no reason why you can't use `URL` and `HttpURLConnection` here and avoid all the HTTP-implementing code altogether. – user207421 Apr 25 '15 at 06:34

2 Answers2

2

You need to add a \r before your \n on all requests, additionally you should flush your output stream to the socket.

Socket socket = new Socket(servername, 80);
DataOutputStream bw = new DataOutputStream(socket.getOutputStream());
bw.writeBytes("GET "+filename+" HTTP/1.1\r\n");
bw.writeBytes("Host: "+servername+":80\r\n\r\n");
bw.flush();

Additionally you will get some HTTP response headers with your request. Obiously this is information you dont want in your image, your response will look something like this:

HTTP/1.1 200 OK
Date: Thu, 14 Nov 2013 18:39:47 GMT
Server: Apache/2.4.3 (Win32) OpenSSL/1.0.1c PHP/5.4.7
Accept-Ranges: bytes
ETag: W/"2956-1374616977919"
Last-Modified: Tue, 23 Jul 2013 22:02:57 GMT
Content-Type: image/png;charset=UTF-8
Content-Length: 2956

‰JPG....heres your image data

I just wrote up this method to get rid of the HTTP headers sent across. The idea is to not write any data before a \r\n\r\n occurrence. That sequence represents the end of the header response and any data before that is not our image. I know there is a cleaner way to do it but this way was fast for me to write :)

OutputStream dos = new FileOutputStream("c:\\testtttt.jpg");
int count;
byte[] buffer = new byte[2048];
boolean eohFound = false;
while ((count = in.read(buffer)) != -1)
{
    if(!eohFound){
        String string = new String(buffer, 0, count);
        int indexOfEOH = string.indexOf("\r\n\r\n");
        if(indexOfEOH != -1) {
            count = count-indexOfEOH-4;
            buffer = string.substring(indexOfEOH+4).getBytes();
            eohFound = true;
        } else {
            count = 0;
        }
    }
  dos.write(buffer, 0, count);
  dos.flush();
}
in.close();
dos.close();

You can also find another question like yours here: Send HTTP Request manually via socket

Community
  • 1
  • 1
ug_
  • 11,267
  • 2
  • 35
  • 52
  • 2
    Is downloading an image from sockets a normal homework question?!... crap – ug_ Nov 14 '13 at 19:00
  • 1
    Thanks a lot for the code, not expecting this, tried it but still when I open the image nothing appears. and now it gives me the size wrong. I am still searching, but thanks again – user2993368 Nov 14 '13 at 19:05
  • 1
    implementing the HTTP protocol manually...? yeah, homework. real code would just use HttpURLConnection or any of the infinite java http clients out there. – jtahlborn Nov 14 '13 at 19:27
  • @user2993368 Try saving it as a txt file and viewing the raw data, then comparing the raw data you downloaded using your code to the actual image you can find your issue. – ug_ Nov 14 '13 at 19:37
  • @jtahlborn I guess it has been to long sense I was in school. But after you say it like that... yea I can see why this is an obvious homework question. – ug_ Nov 14 '13 at 19:38
1

My reputation is not enough to comment, so have to start a new answer.
ug__'s answer is great, but the line

buffer = string.substring(indexOfEOH+4).getBytes();

has some problems, the buffer will be corrupted. For example,

byte[] before = new byte[]{(byte)0xf1, (byte)0xf2, (byte)0xf3, (byte)0xf4};
String str = new String(before, 0, before.length);
byte[] after = str.getBytes();

before and after will not be the same.

So I modified ug__'s code a little bit:

OutputStream dos = new FileOutputStream("test.jpg");
int count, offset;
byte[] buffer = new byte[2048];
boolean eohFound = false;
while ((count = in.read(buffer)) != -1)
{
    offset = 0;
    if(!eohFound){
        String string = new String(buffer, 0, count);
        int indexOfEOH = string.indexOf("\r\n\r\n");
        if(indexOfEOH != -1) {
            count = count-indexOfEOH-4;
            offset = indexOfEOH+4;
            eohFound = true;
        } else {
            count = 0;
        }
    }
  dos.write(buffer, offset, count);
  dos.flush();
}
in.close();
dos.close();
Wenbo
  • 123
  • 1
  • 6