使用HTTP读取文件的第一部分

时间:2010-10-23 15:22:38

标签: java http restlet

我想通过阅读文件的第一部分并分析内容来确定文件的类型(通常为UTF-8)。 (该类型特定于我的社区,但不在我的控制之下,并且不包含在MIME / MediaType中,通常是TEXT_PLAIN)。我正在使用客户端上的'org.restlet'库来分析标题

Request request = new Request(Method.HEAD, url);

所以我知道内容长度并且可以(如果必要和可能)估计我应该下载多少字节用于分析

澄清:我无法使用MediaType。从答案1看起来我必须得到内容。因此,修订后的问题是:

“我可以使用Restlet获取文件的部分吗?”

解答: 以下代码执行我想要的操作。我已经将@BalusC归功于这种方式。如果我遗漏了任何内容,请发表评论:

public String readFirstChunk(String urlString, int byteCount) {
    String text = null;
    if (urlString != null) {
        org.restlet.Client restletClient = new org.restlet.Client(Protocol.HTTP);
        Request request = new Request(Method.GET, urlString);
        List<Range> ranges = Collections.singletonList(new Range(0, byteCount));
        request.setRanges(ranges);
        Response response = restletClient.handle(request);
        if (Status.SUCCESS_OK.equals(response.getStatus())) {
            text = processSuccessfulChunkRequest(response);
        } else if (Status.SUCCESS_PARTIAL_CONTENT .equals(response.getStatus())) {
            text = processSuccessfulChunkRequest(response);
        } else {
            System.err.println("FAILED "+response.getStatus());
        }
    }
    return text;
}

private String processSuccessfulChunkRequest(Response response) {
    String text = null;
    try {
        text = response.getEntity().getText();
    } catch (IOException e) {
        throw new RuntimeException("Cannot download chunk", e);
    }
    return text;
}

3 个答案:

答案 0 :(得分:6)

仅当服务器已将Accept-RangesContent-Range标头与ETagLast-Modified一起发送时,才有可能。 E.g。

Accept-Ranges: bytes
Content-Range: bytes 0-1233/1234
ETag: file.ext_1234_1234567890

Accept-Ranges: bytes表示服务器支持在指定字节范围内返回部分内容的请求。 Content-Range标题通知长度。 ETagLast-Modified表示请求URI后面的资源上的唯一文件标识符或上次修改的时间戳。

如果响应中存在这些标头,那么您可以使用If-RangeRange请求标头分别使用唯一文件标识符或上次修改的时间戳和所需字节来请求资源的一部分范围。

If-Range: file.ext_1234_1234567890
Range: bytes=0-99

上面的例子返回文件的前100个字节。

答案 1 :(得分:1)

如HTTP标准所定义的HEAD操作不返回除标题信息之外的任何内容。因此,如果您要发送头请求,则只能从HTTP响应头中检查文件的MIME类型。

可以通过查看从将其包装到ClientResource并执行头请求而返回的Representation来获取标头信息。这为您提供了HTTP传输的高级接口,您无需进行自定义头解析。

ClientResource resource = new ClientResource(url);
Representation representation = resource.head();
representation.getMediaType(); // returns the Media Type

如果您想对文件的实际内容进行内容类型猜测,则需要下载实际内容,例如使用针对该资源的GET请求。

或者以真正的REST方式,您可以为资源建模一个额外的查询参数,该参数将返回该文件的自定义元信息,例如

http://server/file?contentType

以类似的方式,要检索实际内容,您可以获得Stream的句柄,然后进行编码猜测。

Representation representation = resource.get();
InputStream stream = representation.getStream();

要指定范围,如果服务器支持,您可以在提交获取请求之前设置范围。

List<Range> ranges = new ArrayList<Range>();
ranges.add(new Range(0,100)); // this would request the first 100 bytes
resource.setRanges(ranges);
Representation representation = resource.get();

确保在返回之前完全使用响应(流)。

我建议您查看其他有助于您确定内容类型的工作。 就像这里Java charset and Windowshttp://glaforge.free.fr/wiki/index.php?wiki=GuessEncoding

答案 2 :(得分:0)

既然这是你的内容,为什么不在每个文件的前几个字节中包含你需要的所有数据呢?