Android webview:像浏览器一样下载文件 [英] Android webview: download files like browsers do
问题描述
我正在开发一个 Android 应用,其 web 视图指向另一个团队的动态网站.
当我下载一个文件(主要是动态重定向 PDF 和 ZIP)我得到的只是下载文件夹中的一个文件,其中包含一些 HTML 代码,其中包含一条消息,例如用户不允许读取该文件",不管我怎么实现下载,我都试过了:
I'm working on an Android app with a webview pointing to a dynamic website by another team.
When i download a file (mostly dynamically redirected PDF and ZIP) all i get is a file in the downloads folder containing some HTML code with a message like "user not allowed to read the file", no matter how i implement the download, i tried:
- 下载管理器
- 意图(让外部浏览器管理下载)
- 手动"(AsyncTask 和 httpconnection...)
所有结果都相同.
all with the same results.
使用普通浏览器导航下载工作正常,适用于台式电脑、Android 和 iOS 设备.
为什么 webview 不能访问文件?
可能是会话问题?http 端口?
我真的需要一些想法...
另一个提示:当从同一个链接下载一个文件两次时,该链接将重定向到同一个文件,但会导致两个不同的文件名...
编辑:我没有将 webView 指向 web 应用程序,而是尝试指向一个带有链接重定向的通用网页来下载另一个文件,嗯,它很简单.
以下是 webview.setDownloadListener - onDownloadStart()
参数:
May be a session issue? http port?
I really need some ideas...
Another tip: when downloading twice a file from the same link, the link will redirect to the same file but resulting in two different filenames...
EDIT: Instead of pointing the webView to the web-app, i tried to point to a common webpage with a link-redirect to download another file, well, simply it works.
Here are the webview.setDownloadListener - onDownloadStart()
parameters:
userAgent=Mozilla/5.0 (Linux; Android 4.4.2; Nexus 7 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/30.0.0.0 Safari/537.36
contentDisposition=attachment;
filename=correct_filename.pdf,
url=http://www.xxx.xx/site/downloadfile.wplus?REDIRECTFILE=D-507497120&ID_COUNTOBJ=ce_5_home&TYPEOBJ=CExFILE&LN=2
mimeType=application/octet-stream
这是一些代码
wv.getSettings().setSupportMultipleWindows(true);
wv.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
wv.getSettings().setAllowFileAccess(true);
wv.getSettings().setJavaScriptEnabled(true);
wv.getSettings().setBuiltInZoomControls(true);
wv.getSettings().setDisplayZoomControls(false);
wv.getSettings().setLoadWithOverviewMode(true);
wv.getSettings().setUseWideViewPort(true);
wv.setDownloadListener(new DownloadListener() {
@Override
public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimetype, long contentLength){
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
request.setDescription("Download file...");
request.setTitle(URLUtil.guessFileName(url, contentDisposition, mimetype));
request.allowScanningByMediaScanner();
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); //Notify client once download is completed!
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, URLUtil.guessFileName(url, contentDisposition, mimetype));
DownloadManager dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
dm.enqueue(request);
Toast.makeText(getApplicationContext(), "Downloading File", Toast.LENGTH_LONG).show();
}
}
编辑二
这是我尝试手动"下载文件时使用的代码:
EDIT II
Here's the code i'm using when trying to download files "by hand":
onDownloadStart() 是我调用 downloadFileAsync() 的地方:
onDownloadStart() is where i call downloadFileAsync():
public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimeType, long contentLength) {
String fileName;
try {
fileName = URLUtil.guessFileName(url, contentDisposition, mimeType);
downloadFileAsync(url, fileName);
}catch (Exception e){
}
}
这是异步任务:
private void downloadFileAsync(String url, String filename){
new AsyncTask<String, Void, String>() {
String SDCard;
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected String doInBackground(String... params) {
try {
URL url = new URL(params[0]);
HttpURLConnection urlConnection = null;
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.setDoOutput(true);
urlConnection.connect();
int lengthOfFile = urlConnection.getContentLength();
//SDCard = Environment.getExternalStorageDirectory() + File.separator + "downloads";
SDCard = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)+"";
int k = 0;
boolean file_exists;
String finalValue = params[1];
do {
if (k > 0) {
if (params[1].length() > 0) {
String s = params[1].substring(0, params[1].lastIndexOf("."));
String extension = params[1].replace(s, "");
finalValue = s + "(" + k + ")" + extension;
} else {
String fileName = params[0].substring(params[0].lastIndexOf('/') + 1);
String s = fileName.substring(0, fileName.lastIndexOf("."));
String extension = fileName.replace(s, "");
finalValue = s + "(" + k + ")" + extension;
}
}
File fileIn = new File(SDCard, finalValue);
file_exists = fileIn.exists();
k++;
} while (file_exists);
File file = new File(SDCard, finalValue);
FileOutputStream fileOutput = null;
fileOutput = new FileOutputStream(file, true);
InputStream inputStream = null;
inputStream = urlConnection.getInputStream();
byte[] buffer = new byte[1024];
int count;
long total = 0;
while ((count = inputStream.read(buffer)) != -1) {
total += count;
//publishProgress(""+(int)((total*100)/lengthOfFile));
fileOutput.write(buffer, 0, count);
}
fileOutput.flush();
fileOutput.close();
inputStream.close();
} catch (MalformedURLException e){
} catch (ProtocolException e){
} catch (FileNotFoundException e){
} catch (IOException e){
} catch (Exception e){
}
return params[1];
}
@Override
protected void onPostExecute(final String result) {
}
}.execute(url, filename);
}
取自 如何从网页视图中的动态网址
谢谢
推荐答案
最后我决定寻找Android股票浏览器代码中的DownloadHandler.我的代码中唯一明显的不足是 cookie (!!!).
Finally i decided to look for the DownloadHandler from the Android Stock Browser code. The only noticeable lack in my code was cookie (!!!).
这是我的最终工作版本(DownloadManager 方法):
Here's my final working version (DownloadManager method):
wv.setDownloadListener(new DownloadListener() {
@Override
public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimeType, long contentLength) {
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
request.setMimeType(mimeType);
//------------------------COOKIE!!------------------------
String cookies = CookieManager.getInstance().getCookie(url);
request.addRequestHeader("cookie", cookies);
//------------------------COOKIE!!------------------------
request.addRequestHeader("User-Agent", userAgent);
request.setDescription("Downloading file...");
request.setTitle(URLUtil.guessFileName(url, contentDisposition, mimeType));
request.allowScanningByMediaScanner();
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, URLUtil.guessFileName(url, contentDisposition, mimeType));
DownloadManager dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
dm.enqueue(request);
Toast.makeText(getApplicationContext(), "Downloading File", Toast.LENGTH_LONG).show();
}
});
这篇关于Android webview:像浏览器一样下载文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!