android 下载问题怎么解决方法,Android webview通过http get下载文件下载两次的问题及解决方法 – juejiang...

一、现象

一般通过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数据包。

0f06967592db8fb83a2c26b83e63d14a.png

606f61f3e02cecea112d48585a61b916.png

3b577e5d7a190a301c4905452a089e49.png

二、解决方法

针对这个问题,我觉得比较完美的解决办法是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);

//需要的话可能得增加cookie

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之前的系统应该是适用的。

三、参考材料

8f7abe1114f003f8c0dfd623b619428c.gif

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值