【问题标题】:Download image through sockets java通过sockets java下载图片
【发布时间】:2013-11-27 21:46:10
【问题描述】:

我正在尝试通过套接字从服务器下载图像。我的代码工作正常,但是当我下载图像时,大小正确但图像无法打开。我不知道我做错了什么。有什么建议吗?谢谢

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

【问题讨论】:

  • 您确定图片是 JPG 而不是 PNG?您也可以尝试删除 DataOutputStream 的双重包装。
  • 感谢您的回复。是的,我确定图片是 JPG 格式的,我删除了 DataOutputStream 的双重包装,但它仍然只给了我图片和大小。打不开
  • 不要在循环内刷新。如果你没有使用缓冲流,它什么也不做,如果你是,它完全违背了目的。没有理由不能在这里使用URLHttpURLConnection 并完全避免所有HTTP 实现代码。

标签: java sockets download


【解决方案1】:

我的声誉不足以评论,所以必须开始一个新的答案。
ug__ 的回答很棒,但是这条线

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

有一些问题,缓冲区将被破坏。例如,

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

beforeafter 不会相同。

所以我稍微修改了ug__的代码:

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

【讨论】:

    【解决方案2】:

    您需要在所有请求的 \n 之前添加一个 \r,此外,您应该将输出流刷新到套接字。

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

    此外,您还会在请求中获得一些 HTTP 响应标头。显然这是您不想要的信息,您的回复将如下所示:

    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
    

    我刚刚编写了这个方法来摆脱发送的 HTTP 标头。这个想法是在 \r\n\r\n 发生之前不写入任何数据。该序列表示标头响应的结束,并且在此之前的任何数据都不是我们的图像。我知道有一种更简洁的方法可以做到这一点,但这种方法对我来说写起来很快:)

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

    您还可以在这里找到与您类似的问题:Send HTTP Request manually via socket

    【讨论】:

    • 从套接字下载图像是一个正常的作业问题吗?!...废话
    • 非常感谢代码,没想到会这样,试过了,但是当我打开图像时仍然没有出现。现在它给了我错误的尺寸。我仍在寻找,但再次感谢
    • 手动实现 HTTP 协议...?是的,家庭作业。真正的代码只会使用 HttpURLConnection 或任何无限的 java http 客户端。
    • @user2993368 尝试将其保存为 txt 文件并查看原始数据,然后将使用代码下载的原始数据与您可以找到问题的实际图像进行比较。
    • @jtahlborn 我想我在学校已经很久了。但是在你这样说之后......是的,我明白为什么这是一个明显的家庭作业问题。
    猜你喜欢
    • 1970-01-01
    • 2020-10-29
    • 2012-01-13
    • 2020-10-08
    • 2011-03-03
    • 1970-01-01
    • 2014-01-01
    • 2021-01-29
    • 2013-07-03
    相关资源
    最近更新 更多