Java 获取未压缩的gzip文件的大小,而服务器可以提供压缩文件的大小

Java 获取未压缩的gzip文件的大小,而服务器可以提供压缩文件的大小,java,android,gzip,Java,Android,Gzip,我正在使用GZIPInputStream下载PDF文件。我想在UI按钮上显示文件的下载进度。但是,我没有得到文件的实际大小,我得到的是压缩大小,因此我无法显示正确的下载进度。此下载进度超过100,因为实际文件大小大于文件的压缩大小 来自服务器的文件头内容:我从服务器接收到以下信息,从中我使用内容长度,它给出了压缩文件的大小 1.Connection 2.Content-Encoding 3.Content-length 4.Content-Type 5.Keep-Alive 6.Server 7

我正在使用
GZIPInputStream
下载PDF文件。我想在UI按钮上显示文件的下载进度。但是,我没有得到文件的实际大小,我得到的是压缩大小,因此我无法显示正确的下载进度。此下载进度超过
100
,因为实际文件大小大于文件的压缩大小

来自服务器的文件头内容:我从服务器接收到以下信息,从中我使用
内容长度
,它给出了压缩文件的大小

1.Connection
2.Content-Encoding
3.Content-length
4.Content-Type
5.Keep-Alive
6.Server
7.Date
这是我的密码。有没有办法获得文件的原始大小

long fileLength =  httpResponse.getEntity().getContentLength();//
GZIPInputStream input = new GZIPInputStream(new BufferedInputStream(
        httpResponse.getEntity().getContent()));
FileOutputStream output = new FileOutputStream(destinationFilePath);

byte data[] = new byte[1024];
long total = 0;
float percentage = 0;
int count;
currentDownloadingPercentage=0;
while ((count = input.read(data)) != -1) {
    total += count;
    output.write(data, 0, count);

    // publishing the progress....
    percentage = (float)total/(float)fileLength;
    percentage *= 100;
    if ((int)percentage > (int)currentDownloadingPercentage) {
        currentDownloadingPercentage = percentage;
        Bundle resultData = new Bundle();
        resultData.putBoolean(DOWNLOAD_FAILED, false);
        resultData.putInt(DOWNLOAD_PROGRESS ,(int)percentage);
        receiver.send(processID, resultData);
        resultData = null;  
    }
}

你看得不对。您应该计算读取的压缩字节数,并根据这些字节计算进度。相反,您要计算解压缩的字节数,并将其与压缩文件大小进行比较。在回答您的问题时,没有(可靠的)方法可以在不解压缩的情况下确定gzip文件的大小

更新:这里有一种方法可以计算输入的未压缩字节数。在使用GZIPInputStream包装原始输入流之前,先使用包装。将TeInputStream分支设为。然后您将始终拥有通过下载的压缩字节的当前计数。此讨论结果似乎无法避免HttpURLConnection。getInputStream()自动返回GZIPInputStream,一旦您让HttpURLConnection接受gzip压缩,您将无法准确计算下载进度,我们唯一能做的就是禁用gzip作为可接受的编码:

HttpURLConnection.setRequestProperty("Accept-Encoding", "identity");
另一个选择是使用,我已经对此进行了测试,即使我们现在接受gzip编码,如下所示:

HttpUriRequest.addHeader("Accept-Encoding", "gzip");
通过HttpResponse.getEntity().getContent()返回的InputStream实例将是EofSensorInputStream,原始InputStream是我们想要的,不是GZIPInputStream,这使我们能够自己将其包装到GZIPInputStream,我们可以使用TeeInputStream和CountingOutputStream来完成下载进度的计算

HttpResponse response = ...;
HttpEntity entity = response.getEntity();
long fileSize = entity.getContentLength();

InputStream ins = entity.getContent(); // instance of EofSensorInputStream
CountingOutputStream coStrem = new CountingOutputStream(new ByteArrayOutputStream(100));
GZIPInputStream inStrem = new GZIPInputStream(new TeeInputStream(ins, coStrem, true));

byte[] buffer = new byte[6 * 1024]; // 6K buffer
int offset;

while ((offset = inStrem.read(buffer)) != -1) {
    tmpFileRaf.write(buffer, 0, offset);
    postDownloadProgress(fileSize, coStrem.getByteCount());
}
我想这就是我们解决这个问题所能做的,我试着用我的项目获取源代码,这样我们就可以自定义HttpURLConnectionImpl,然后抑制它返回GZIPInputStream,但是很多错误都会带来麻烦,我放弃了这一努力


在这篇文章中,Jesse Wilson建议我们Android的最佳选择客户端是HttpURLConnection,所以我一直在寻找如何解决这个问题的方法,我希望我能尽快找到解决方法。

我也尝试过使用InputStream,这在进度方面很好,但流产生了一个压缩文件。在脱机模式下,解压缩此文件需要比平时更多的时间。对文件逐字节进行解压缩需要花费整整一轮的时间。下面是只读取压缩字节的代码..InputStream input=new BufferedInputStream(httpResponse.getEntity().getContent());我已经用一种方法更新了我的答案,可以动态计算压缩的字节数。Ryan,在android中我应该怎么做?在安卓系统中有没有TeInputStream的替代方案?哦,我没注意到你在安卓系统上。编写自己的并不困难,而且commons io是开源的,所以您可以从那里获取源文件。