Android / Java: HttpURLConnection не возвращает заголовки перенаправленного файла (например, на S3) - PullRequest
7 голосов
/ 25 февраля 2011

Мой код (воспроизводится ниже), подключается к URL и загружает файл на диск на Android.Все стандартные вещи.Когда я пытаюсь использовать этот код в файле на S3, доступ к которому осуществляется через поддомен на нашем сервере, сопоставленном с корзиной (например, foo.example.com => bucket с именем foo.example.com), это часто приводит к сбою.Оказывается (используя команду handy 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);
            }

Ответы [ 3 ]

10 голосов
/ 25 февраля 2011

пытались ли вы установить для перенаправлений значение 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, но вы можете легко настроить это, чтобы попробовать для любого другого поля заголовка.Это помогает?

1 голос
/ 09 июня 2015

Рассмотрите возможность использования httpclient-android .Вы должны получить правильные заголовки после перенаправления:

HttpClient client = HttpClientBuilder.create().build();
HttpGet request = new HttpGet(YOUR_URL);
HttpResponse response = client.execute(request);
response.getAllHeaders()

Обратите внимание, что Android поставляется с более старой версией httpclient, но у него та же проблема, о которой вы сообщали.* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} * * * * * * * * * * * * * * * * * * * * * * * * * * * Примечание: код

Примечание: код фрагмента для v4.3.Для других версий ищите, как это сделать в обычном apache HttpClient.

0 голосов
/ 28 февраля 2011

Ну, я немного поиграл, и этот код, который использует библиотеку 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();
    }
}
}
...