Как сохранить куки из WebViewClient в URLConnection, браузер или другой метод загрузки файлов в Android - PullRequest
6 голосов
/ 08 марта 2011

У нас есть сайт с поддержкой авторизации форм .net, который пользователь посещает через WebViewClient в нашем приложении для Android. Одной из особенностей сайта является возможность входа и загрузки некоторых файлов PDF, однако для загрузки файлов PDF необходимо войти в систему.

В настоящее время мы внедряем shouldOverrideUrlLoading и загружаем pdf через следующий код, когда выполняется правильное условие.

URL u = new URL(url);
URLConnection conn = u.openConnection();
int contentLength = conn.getContentLength();

DataInputStream stream = new DataInputStream(u.openStream());

byte[] buffer = new byte[contentLength];
stream.readFully(buffer);
stream.close();

DataOutputStream fos = new DataOutputStream(new FileOutputStream("/sdcard/download/file.pdf"));
fos.write(buffer);
fos.flush();
fos.close();

Из журналов IIS очевидно, что IIS не считает этот запрос входящим в систему и перенаправляет его на страницу входа.

Нам нужен способ загрузки файла с сохраненным файлом cookie аутентификации в запросе на загрузку файла, но мы не знаем, как сохранить файл cookie.

Другим жизнеспособным решением для нас является сохранение cookie-файла авторизации между WebViewClient и браузером Android. Если бы мы могли это сделать, мы бы просто открыли файл PDF с помощью действия по умолчанию в браузере.

Редактировать: Похоже, я могу вручную установить файл cookie с помощью

conn.setRequestProperty("Cookie", "");

Теперь мне просто нужно выяснить, как считывать файл cookie аутентификации из WebViewClient

Ответы [ 2 ]

8 голосов
/ 09 марта 2011

Поскольку вы используете проверку подлинности ASP.NET Forms , вам необходимо скопировать файл проверки подлинности форм из WebView в URLConnection. К счастью, это довольно просто. Этот код живет в реализации shouldOverrideUrlLoading

string url = "http://site/generatePdfBehindFormsAuth";

// get an instance of a cookie manager since it has access to our auth cookie
CookieManager cookieManager = CookieManager.getInstance();

// get the cookie string for the site.  This looks something like ".ASPXAUTH=data"
String auth = cookieManager.getCookie(url).toString();

URLConnection conn = (URLConnection)new URL(url).openConnection();

// Set the cookie string to be sent for download.  In our case we're just copying the
//   entire cookie string from the previous connection, so all values stored in 
//   cookies are persisted to this new connection.  This includes the aspx auth 
//   cookie, otherwise it would not be authenticated
//   when downloading the file.  
conn.setRequestProperty("Cookie", auth);
conn.setDoOutput(true);
conn.connect();

// get the filename from the servers response, its typical value is something like:
//   attachment; filename="GeneratedPDFFilename.pdf"
String filename = conn.getHeaderField("Content-Disposition").split("\"")[1];

// by default, we'll store the pdf in the external storage directory
String fileRoot = "/sdcard/";

// Complete the download
FileOutputStream f = new FileOutputStream(new File(fileRoot, filename));
InputStream in = conn.getInputStream();
byte[] buffer = new byte[1024];
int len1 = 0;
while ( (len1 = in.read(buffer)) > 0 ) 
{
    f.write(buffer,0, len1);
}
f.close();
in.close();

ПРИМЕЧАНИЕ: Обращаем ваше внимание на то, что вам следует НЕ позвонить getContentLength на ваш URLConnection. После 4 часов отладки wireshark наконец-то показал, что если вы позвоните getContentLength, файл cookie будет отправлен для запроса, который получает длину содержимого, но файл cookie не будет отправлен для последующего запросы даже на один и тот же экземпляр URLConnection . Возможно, я наивен, и это из-за намерения (в документации не указано, что это из-за замысла), но мне не удалось вручную установить cookie для последующего запроса файла, вызвав setRequestProperty после вызова getContentLength. Если бы я попытался сделать это, я бы приблизился к силе.

1 голос
/ 08 марта 2011

Вы смотрели на класс CookieSyncManager?Я считаю, что это необходимо для сохранения файлов cookie, полученных с сервера, и их повторного использования.

http://developer.android.com/reference/android/webkit/CookieSyncManager.html

...