HTTP Range标头没有使用Java提供正确的输出

时间:2015-03-03 13:59:09

标签: java sockets http

我正在编写一个简单的Java代码,只需从远程服务器下载文件即可。我没有使用太多的Java类。我正在创建一个简单的java.net.Socket并在输出流上编写原始HTTP代码,如下所示:

Downloader.java

import java.io.*;
import java.net.*;
import java.util.*;




public class Downloader {

    Socket socket;
    InputStream istream;
    Scanner scanner;
    OutputStream ostream;
    PrintWriter writer;

    String request;



    public Downloader() {

        socket = null;
        istream = null;
        scanner = null;
        ostream = null;
        writer = null;  
    }



    public static void main(String[] args) throws IOException {

            Downloader downloader = new Downloader();
            downloader.initDownload("cdn.mysql.com", 80, "/Downloads/MySQL-5.6/mysql-5.6.23-osx10.8-x86_64.tar.gz");
            downloader.download();
            downloader.close();
    }



    public void initDownload(String host, int port, String file) throws IOException {
        // Connecting the socket.
        socket = new Socket(host, port);

        // Generating the HTTP request
        request  = "GET "+file+" HTTP/1.1\r\n";
        request += "Host: "+host+":"+port+"\r\n";
        request += "User-Agent: \r\n";
        request += "Connection: Close\r\n";
        request += "Range: bytes=0-1000\r\n";   // This line doesn't work properly.
        request += "\r\n";
    }



    public void download() throws IOException {

        ostream = socket.getOutputStream();
        writer = new PrintWriter(ostream);

        writer.println(request);
        writer.flush();

        read();
    }



    public void read() throws IOException {

        istream = socket.getInputStream();
        scanner = new Scanner(istream);

        // Print the HTTP response by the server on the terminal.
        while(scanner.hasNextLine()) {

            String line = scanner.nextLine();
            System.out.println(line);
            if(line.length() == 0)  // break out of the loop when we encounter an empty line. i.e., The blank line between HTTP headers and body.
                break;
        }


        // Print the data in the file "mysql-5.6.23-osx10.8-x86_64.tar.gz"
        FileOutputStream fostream = new FileOutputStream("mysql-5.6.23-osx10.8-x86_64.tar.gz", true);
        while(scanner.hasNextLine())
            fostream.write(scanner.nextLine().getBytes());
        fostream.close();   
    }



    public void close() throws IOException {

        istream.close();
        scanner.close();
        ostream.close();
        writer.close();
        socket.close();
    }
}  

我想,代码很安静。我试图使用普通套接字从服务器读取文件。代码工作正常。服务器的响应头在终端窗口输出,而数据在文件中输出。但是Range标题没有给出正确的输出。

当我运行代码时,这是HTTP server response打印的:

HTTP/1.1 206 Partial Content
Server: Apache
Accept-Ranges: bytes
Last-Modified: Tue, 20 Jan 2015 06:15:42 GMT
ETag: "5f989776b8f8766c7f43c27c1a09c032:1422821798"
Date: Tue, 03 Mar 2015 13:35:54 GMT
Content-Range: bytes 0-1000/176674931  // Looke here. The output is fine here.
Content-Length: 1001
Connection: close
Content-Type: application/x-tar-gz  

数据进入文件mysql-5.6.23-osx10.8-x86_64.tar.gz

但是当我右键单击文件mysql-5.6.23-osx10.8-x86_64.tar.gz来查看它的大小时,它的大小为1,835 bytes而不是1,001 bytes

为什么会这样?我该怎么做才能克服它?请帮忙。

PS:

  1. 我不想使用任何其他内置课程。我希望通过原始HTTP来做到这一点。提前致谢。
  2. 我使用的是Macbook Pro,Mac OS X Yosemite,64位。

1 个答案:

答案 0 :(得分:0)

参考 - http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html。它表明服务器可以忽略范围请求,这就是我想要的情况。