在Android上下载带有传输编码标头的文件
我有一个奇怪的问题,我真的想对此有一些见解。我有一些代码来下载各种文件。有些文件返回值为“chunked”的“transfer-encoding”标头,我很确定这就是导致我出现问题的原因。
这就是事情变得非常奇怪的地方。在我的 Motorolla Droid 3g 上下载时,具有此编码的文件无法正确下载,因为它在读取所有字节之前完成下载,因此我的文件已损坏。然而,在使用 WiFi 的同一部手机上下载相同的文件就可以了。
这听起来像是服务器问题吗?安卓问题? 3g问题?我的代码问题?
这是我用来读取响应标头的一些代码:
private void readResponseHeaders(HttpResponse response) throws StopRequest {
Header header = response.getFirstHeader("Content-Disposition");
if (header != null) {
mInfo.mInnerState.mHeaderContentDisposition = header.getValue();
}
header = response.getFirstHeader("Content-Location");
if (header != null) {
mInfo.mInnerState.mHeaderContentLocation = header.getValue();
}
if (mInfo.mMimeType == null) {
header = response.getFirstHeader("Content-Type");
if (header != null) {
mInfo.mMimeType = sanitizeMimeType(header.getValue());
}
}
header = response.getFirstHeader("ETag");
if (header != null) {
mInfo.mInnerState.mHeaderETag = header.getValue();
}
String headerTransferEncoding = null;
header = response.getFirstHeader("Transfer-Encoding");
if (header != null) {
headerTransferEncoding = header.getValue();
}
if (headerTransferEncoding == null) {
header = response.getFirstHeader("Content-Length");
if (header != null) {
mInfo.mInnerState.mHeaderContentLength = header.getValue();
mInfo.mTotalBytes = Long.parseLong(mInfo.mInnerState.mHeaderContentLength);
if (!mFileManager.hasSufficientSpace(mInfo.mTotalBytes, mBasePath)){
throw new StopRequest(ServiceDownloadConstants.STATUS_INSUFFICIENT_SPACE_ERROR, "Not Enough Space");
}
}
} else {
// Ignore content-length with transfer-encoding - 2616 4.4 3
if (ServiceDownloadConstants.LOGVV) {
Log.v(ServiceDownloadConstants.TAG,
"ignoring content-length because of xfer-encoding");
}
}
if (ServiceDownloadConstants.LOGVV) {
Log.v(ServiceDownloadConstants.TAG, "Content-Disposition: " + mInfo.mInnerState.mHeaderContentDisposition);
Log.v(ServiceDownloadConstants.TAG, "Content-Length: " + mInfo.mInnerState.mHeaderContentLength);
Log.v(ServiceDownloadConstants.TAG, "Content-Location: " + mInfo.mInnerState.mHeaderContentLocation);
Log.v(ServiceDownloadConstants.TAG, "Content-Type: " + mInfo.mMimeType);
Log.v(ServiceDownloadConstants.TAG, "ETag: " + mInfo.mInnerState.mHeaderETag);
Log.v(ServiceDownloadConstants.TAG, "Transfer-Encoding: " + headerTransferEncoding);
}
boolean noSizeInfo = mInfo.mInnerState.mHeaderContentLength == null
&& (headerTransferEncoding == null
|| !headerTransferEncoding.equalsIgnoreCase("chunked"));
if (!mInfo.mNoIntegrity && noSizeInfo) {
throw new StopRequest(ServiceDownloadConstants.STATUS_HTTP_DATA_ERROR,
"can't know size of download, giving up");
}
}
这是我用来传输数据的一些代码:
private void transferData(byte[] data, InputStream entityStream) throws StopRequest {
for (;;) {
int bytesRead = readFromResponse( data, entityStream);
if (bytesRead == -1) {
// success, end of stream already reached
handleEndOfStream();
return;
}
writeDataToDestination(data, bytesRead);
mInfo.mInnerState.mBytesSoFar += bytesRead;
/** Update SHA1 if needed **/
if( mInfo.mEnclosure.getHash() != null && mSha1 != null ){
mSha1.update( data, 0, bytesRead );
}
if (ServiceDownloadConstants.LOGVV) {
Log.v(ServiceDownloadConstants.TAG, "downloaded " + mInfo.mInnerState.mBytesSoFar + " for "
+ mInfo.mEnclosure.getUrl());
}
checkPausedOrCanceled();
}
}
编辑 经过进一步调试,即使没有发送“传输编码”标头,我也收到了完全相同的结果,所以看来我的问题是通用的,因为它在 Wifi 上工作,但在 3G 上不起作用。
I have a strange problem that I would really some insight on. I have some code to download various files. Some files return the "transfer-encoding" header with a value of "chunked" and I'm pretty sure this is what's causing me problems.
Here's where it gets really strange. When downloading on my Motorolla Droid on 3g the files with this encoding do not download correctly, as in it finishes downloading before all the bytes have been read, therefore I have a corrupt file. However, on the exact same phone using WiFi the same file download just fine.
Does this sound like it would this be a server issue? android issue? 3g issue? my code issue?
Here's some code I'm using to read the response headers:
private void readResponseHeaders(HttpResponse response) throws StopRequest {
Header header = response.getFirstHeader("Content-Disposition");
if (header != null) {
mInfo.mInnerState.mHeaderContentDisposition = header.getValue();
}
header = response.getFirstHeader("Content-Location");
if (header != null) {
mInfo.mInnerState.mHeaderContentLocation = header.getValue();
}
if (mInfo.mMimeType == null) {
header = response.getFirstHeader("Content-Type");
if (header != null) {
mInfo.mMimeType = sanitizeMimeType(header.getValue());
}
}
header = response.getFirstHeader("ETag");
if (header != null) {
mInfo.mInnerState.mHeaderETag = header.getValue();
}
String headerTransferEncoding = null;
header = response.getFirstHeader("Transfer-Encoding");
if (header != null) {
headerTransferEncoding = header.getValue();
}
if (headerTransferEncoding == null) {
header = response.getFirstHeader("Content-Length");
if (header != null) {
mInfo.mInnerState.mHeaderContentLength = header.getValue();
mInfo.mTotalBytes = Long.parseLong(mInfo.mInnerState.mHeaderContentLength);
if (!mFileManager.hasSufficientSpace(mInfo.mTotalBytes, mBasePath)){
throw new StopRequest(ServiceDownloadConstants.STATUS_INSUFFICIENT_SPACE_ERROR, "Not Enough Space");
}
}
} else {
// Ignore content-length with transfer-encoding - 2616 4.4 3
if (ServiceDownloadConstants.LOGVV) {
Log.v(ServiceDownloadConstants.TAG,
"ignoring content-length because of xfer-encoding");
}
}
if (ServiceDownloadConstants.LOGVV) {
Log.v(ServiceDownloadConstants.TAG, "Content-Disposition: " + mInfo.mInnerState.mHeaderContentDisposition);
Log.v(ServiceDownloadConstants.TAG, "Content-Length: " + mInfo.mInnerState.mHeaderContentLength);
Log.v(ServiceDownloadConstants.TAG, "Content-Location: " + mInfo.mInnerState.mHeaderContentLocation);
Log.v(ServiceDownloadConstants.TAG, "Content-Type: " + mInfo.mMimeType);
Log.v(ServiceDownloadConstants.TAG, "ETag: " + mInfo.mInnerState.mHeaderETag);
Log.v(ServiceDownloadConstants.TAG, "Transfer-Encoding: " + headerTransferEncoding);
}
boolean noSizeInfo = mInfo.mInnerState.mHeaderContentLength == null
&& (headerTransferEncoding == null
|| !headerTransferEncoding.equalsIgnoreCase("chunked"));
if (!mInfo.mNoIntegrity && noSizeInfo) {
throw new StopRequest(ServiceDownloadConstants.STATUS_HTTP_DATA_ERROR,
"can't know size of download, giving up");
}
}
Here's some code I'm using to transfer the data:
private void transferData(byte[] data, InputStream entityStream) throws StopRequest {
for (;;) {
int bytesRead = readFromResponse( data, entityStream);
if (bytesRead == -1) {
// success, end of stream already reached
handleEndOfStream();
return;
}
writeDataToDestination(data, bytesRead);
mInfo.mInnerState.mBytesSoFar += bytesRead;
/** Update SHA1 if needed **/
if( mInfo.mEnclosure.getHash() != null && mSha1 != null ){
mSha1.update( data, 0, bytesRead );
}
if (ServiceDownloadConstants.LOGVV) {
Log.v(ServiceDownloadConstants.TAG, "downloaded " + mInfo.mInnerState.mBytesSoFar + " for "
+ mInfo.mEnclosure.getUrl());
}
checkPausedOrCanceled();
}
}
Edit
Upon further debugging, I've received the exact same results even when the "transfer-encoding" header isn't being sent, so it would seem my problem is as generic as it works on Wifi and it doesn't on 3g.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
3G 提供商会缓存文件,但缓存有时会被破坏。尝试根据您的请求设置无缓存标头。
3G providers cache files, and caching is sometimes broken. Try to set no-cache headers on your request.