展会信息港展会大全

Android webview通过http get下载文件下载两次的问题及解决方法
来源:互联网   发布日期:2015-10-02 21:27:07   浏览:1680次  

导读:一、现象 一般通过Android webview进行下载文件的方法是 1.重写DownloadListener的onDownloadStart方法,在onDownloadS...

一、现象

一般通过Android webview进行下载文件的方法是

1.重写DownloadListener的onDownloadStart方法,在onDownloadStart方法中弹出对话框提示用户有新的文件需要下载

2.用户点击确定之后,通过http get下载文件

由于Android webview的实现,以上的下载文件步骤涉及到了两次get的操作。第一次是用户在webview中点击下载链接时,webview自动发送http get请求,这个时候服务器除了将文件信息发送过来之外,会同时将文件的内容发送给webview。第二次是在步骤2,由自己设计的程序发起的。

为了验证如上结论,我在Android 4.4系统中的自带浏览器通过访问并下载这个测试链接,并用wireshark进行抓包查看结果。通过如下三张图,我觉得可以验证同一份文件确实被传了两次。因为两个不同http get请求之后都可以看到服务器向客户端发送的连续的TCP数据包。

二、解决方法

针对这个问题,我觉得比较完美的解决办法是webview在进行get的时候能够缓存相应的文件内容,并且开放相应的接口给应用进行缓存的读龋但是我并没有发现相应的api。

于是便有了如下的解决办法:在webview加载url之前,通过链接中的一些特定字段发现进行下载操作。然后通过http head请求获取文件名和大小等相关信息。由于http head只是请求文件相关信息,所以服务器只是通过http response将文件信息返回而不通过tcp发送文件具体内容。

2.1 在继承自WebViewClient的类的shouldOverrideUrlLoading方法中检查链接类型,并通过http head获取文件大小,名称信息。在以下代码基础上需要增加合适的获取文件名称代码和handler的代码。

if (url.contains("可能会进行下载的链接字段")) {

new Thread() {

public void run() {

HttpHead httpGet = new HttpHead(mUrl);

boolean success = true;

String filename="";

Integer fileLength=100;

try {

HttpParams httpParameters = new BasicHttpParams();

HttpConnectionParams.setConnectionTimeout(httpParameters, 8000);

HttpConnectionParams.setSoTimeout(httpParameters, 8000);

DefaultHttpClient httpClient = new DefaultHttpClient(httpParameters);<br>

//需要的话可能得增加cookie<br>

HttpResponse httpResponse = httpClient.execute(httpGet);

if (httpResponse.getStatusLine().getStatusCode() == 200) {//如果文件名保存在Content-Disposition中,并且用的是gb2312编码方式可以参考这段代码

String nameString=httpResponse.getFirstHeader("Content-Disposition").getValue();

char [] nameChar=new char[nameString.length()];

byte [] nameBytes=new byte[nameString.length()];

nameString.getChars(0, nameString.length(), nameChar, 0);

for (int i = 0; i < nameChar.length; i++) {

nameBytes[i]=(byte)nameChar[i];

}

filename=EncodingUtils.getString(nameBytes, "gb2312");

Log.d(TAG, "file name is "+filename);

String contentLength=httpResponse.getFirstHeader("Content-Length").getValue();

fileLength=Integer.parseInt(contentLength);

success=true;

}else {

success=false;

}

} catch (Exception e) {

success = false;

e.printStackTrace();

}

Message msg = Message.obtain();

if(success) {

msg.what = GET_FILE_INFO_FINISHED;

Bundle mBundle=new Bundle();

mBundle.putString("fileName", filename);

mBundle.putInt("fileLength", fileLength);

msg.setData(mBundle);

}

else {

msg.what = GET_FILE_INFO_FAILED;

}

mHandler.sendMessage(msg);

}

}.start();

}else {

view.loadUrl(url);

}

2.2 适用情况

在Android 4.4中,根据网页的特点,可能会出现点击下载链接,而shouldOverrideUrlLoading不被调用的情况,这时2.1中方法则失效了。不过对于4.4之前的系统应该是适用的。

赞助本站

人工智能实验室

相关热词: android开发

AiLab云推荐
展开

热门栏目HotCates

Copyright © 2010-2024 AiLab Team. 人工智能实验室 版权所有    关于我们 | 联系我们 | 广告服务 | 公司动态 | 免责声明 | 隐私条款 | 工作机会 | 展会港