Android/Java:HttpURLConnection不';t返回重定向文件的标题(例如在S3上)

Android/Java:HttpURLConnection不';t返回重定向文件的标题(例如在S3上),android,redirect,download,httpurlconnection,Android,Redirect,Download,Httpurlconnection,我的代码(复制如下)连接到一个url,并将文件下载到android上的磁盘上。所有标准的东西。当我尝试在S3上的一个文件上使用此代码时,该文件是通过服务器上映射到bucket(例如foo.example.com=>bucket,名为foo.example.com)的子域访问的,它经常失败。结果是(使用方便的curl命令 "curl -v -L -X GET http://foo.example.com/f/a.txt") …这里有一个重定向 文件下载工作正常,因为默认情况下HttpURLC

我的代码(复制如下)连接到一个url,并将文件下载到android上的磁盘上。所有标准的东西。当我尝试在S3上的一个文件上使用此代码时,该文件是通过服务器上映射到bucket(例如foo.example.com=>bucket,名为foo.example.com)的子域访问的,它经常失败。结果是(使用方便的curl命令

 "curl -v -L -X GET http://foo.example.com/f/a.txt") 
…这里有一个重定向

文件下载工作正常,因为默认情况下HttpURLConnection将遵循重定向,但需要标头信息(getContentLength、getHeaderFieldDate(“Last Modified”,0)等)的调用将返回307重定向中的标头,而不是下载的实际文件

有人知道怎么避开这个吗

谢谢

File local = null;
        try {


            Log.i(TAG, "Downloading file " + source);
            conn = (HttpURLConnection) new URL(source).openConnection();
            fileSize = conn.getContentLength(); // ** THIS IS WRONG ON REDIRECTED FILES
            out = new BufferedOutputStream(new FileOutputStream(destination, false), 8 * 1024); 
            conn.connect();

            stream = new BufferedInputStream(conn.getInputStream(), 8 * 1024);

            byte[] buffer = new byte[MAX_BUFFER_SIZE];

            while (true) {
                int read = stream.read(buffer);

                if (read == -1) {
                    break;
                }
                // writing to buffer
                out.write(buffer, 0, read);
                downloaded += read;

                publishProgress(downloaded, fileSize);

                if (isCancelled()) {
                    return "The user cancelled the download"; 
                }

            }
        } catch (Exception e) {
            String msg = "Failed to download file " + source + ". " + e.getMessage();
            Log.e(TAG, msg );
            return msg;
        } finally {
            if (out != null) {
                try {
                    out.flush();
                    out.close();
                } catch (IOException e) {
                    Log.e(TAG, "Failed to close file " + destination);
                    e.printStackTrace();
                }
            }

            if (stream != null) {
                try {
                    stream.close();
                } catch (IOException e) {
                    Log.e(TAG, "Failed to close file " + destination);
                    e.printStackTrace();
                }

            } else {

                long dateLong = conn.getHeaderFieldDate("Last-Modified", 0 ); // ** THIS IS WRONG ON REDIRECTED FILES

                Date d = new Date(dateLong);
                local.setLastModified(dateLong);
            }

您是否尝试将重定向设置为false,并尝试手动捕获重定向的URL及其关联的标题字段

例如,类似这样的事情:

URL url = new URL(url); 
HttpURLConnection ucon = (HttpURLConnection) url.openConnection(); 
ucon.setInstanceFollowRedirects(false); 
URL secondURL = new URL(ucon.getHeaderField("Location")); 
URLConnection conn = secondURL.openConnection();

此示例捕获重定向的URL,但您可以轻松地调整它以尝试任何其他标头字段。这是否有帮助?

好吧,我已经播放了一段时间,这段代码使用HttpClient库而不是HttpUrlConnection运行良好。它返回的标头是最终重定向跃点的标头。 至少在我测试过的设备上

HttpClient client = null;
HttpGet get = null;
HttpResponse response = null;
try {
client = new DefaultHttpClient();
get = new HttpGet(source);
response = client.execute(get);

Header contentSize = response.getFirstHeader("Content-Length");
if (contentSize != null) {
 String value = contentSize.getValue();
 fileSize = Long.parseLong(value);
}
if (fileSize == -1) {
    Log.e(TAG, "Failed to read the content length for the file " + source);
}

Header lastModified = response.getFirstHeader("Last-Modified");
lastModifiedDate = null;
if (lastModified != null) {
    lastModifiedDate = DateUtils.parseDate(lastModified.getValue());
}
if (lastModifiedDate == null) {
    Log.e(TAG, "Failed to read the last modified date for the file " + source);
}

out = new BufferedOutputStream(new FileOutputStream(destination, false), 8 * 1024);     // false means don't append
stream = new BufferedInputStream(response.getEntity().getContent(), 8 * 1024);

byte[] buffer = new byte[MAX_BUFFER_SIZE];

int count = 0;
while (true) {
    int read = stream.read(buffer);

    if (read == -1) {
        break;
    }
    // writing to buffer
    out.write(buffer, 0, read);
    downloaded += read;

    publishProgress(downloaded, fileSize);

    if (isCancelled()) {
        Log.w(TAG, "User Cancelled");
        return; // NOTE that onPostExecute is not called here..
    }
}// end of while

publishProgress(downloaded, fileSize);

} catch (Exception e) {
String msg = "Failed to download file " + source + ". " + e.getMessage();
Log.e(TAG, msg );
return msg;
} finally {
if (out != null) {
    try {
        out.flush();
        out.close();
    } catch (IOException e) {
        Log.e(TAG, "Failed to close file " + destination);
        e.printStackTrace();
    }
}

if (stream != null) {
    try {
        stream.close();
    } catch (IOException e) {
        Log.e(TAG, "Failed to close file " + destination);
        e.printStackTrace();
    }
}
}
考虑使用。重定向后,您应该使用以下命令获得正确的头:

HttpClient client = HttpClientBuilder.create().build();
HttpGet request = new HttpGet(YOUR_URL);
HttpResponse response = client.execute(request);
response.getAllHeaders()
请注意,android附带了一个较旧版本的httpclient,但它与您报告的问题相同。您需要导入“httpclient android”以获得较新版本


注意:代码片段是针对v4.3的。对于其他版本,请查看如何在常规apache HttpClient中执行此操作。

谢谢。我想它可能会对多个重定向有点麻烦,但这可能会很有帮助。我在各种Android组件的重定向代码中遇到了其他奇怪的问题。即使在同一操作系统版本上,不同的设备也会处理这些问题结果我们切换到了手动重定向。啊,很有趣。我一直在尝试使用apache HttpClient而不是HttpURLConnection,它对我很有效(到目前为止!).您对哪些android组件有问题?我使用的代码几乎完全相同,它在android 4.1 emulator中给出重定向的url,但在android 2.2.2设备中相同的代码返回“null”!您知道为什么会失败吗?