Android实现单线程异步多文件下载的代码

简介:

 现在有一个需求,需要下载的文件有很多个,放在一个开放端口(URL)的目录下,这个目录下的文件会变动,就是文件名不定。现在需要把这个目录下的文件下载到Android设备上。我找了很多资料,发现不能把一个URL目录下的全部文件以文件名的方式列出来(?)。那么,把需要下载的多个文件打包成一个.zip文件放到URL上,下载下来后再通过代码解压,解压时如果有中文名的文件,不能正常解压(这个在另一篇文章中记载)。走另一条道路:需要下载的文件关联到一个点菜系统的菜单的全部图片,文件名就是菜单的图片名。点菜系统的菜单可以从服务器的数据库中查询到。这样就把菜单全部遍历一遍,每个菜单的图片名(如果有的话)和URL目录拼成文件下载路径(经理提出的方法),使用循环遍历下载。

/**
  * 准备下载菜谱图片,检查SDcard是否可用,设置下载更新地址,下载后保存位置信息。
  */
 private void downloadMenuImageCheck() {
  String status = Environment.getExternalStorageState();
  if (!Environment.MEDIA_MOUNTED.equals(status)) {
   ToastUtils.showFailure(getApplicationContext(),
     "SDcard cannot use!");
   return;
  }

  RequestFileInfo requestFileInfo = new RequestFileInfo();
  requestFileInfo.fileParentUrl = "http://192.168.1.103:8181/menupic";
  requestFileInfo.saveFilePath = Environment
    .getExternalStorageDirectory().getAbsolutePath()
    + "/waitab/menupic";

  showDialog(DialogUtil.DIALOG_DOWNLAOD_IMAGE_PROGRESS);   
  new DownlaodUpdateTask().execute(requestFileInfo);
 }

 /**
  * 找出所有菜品数据
  * @return List<menux>
  */
 private List<menux> updateMenux() {
  return mdb.findAll();
 }

 /**
  * 找出所有菜品数据
  * 下载菜品图片类 
  * 遍历菜品数据List,根据每一个菜品图片名字拼出下载路径
  * 多文件循环遍历单线程下载
  * 
  * @author modify by ZX
  * 
  */
 private class DownlaodUpdateTask extends
   AsyncTask<requestfileinfo progressvalue="" basiccallresult=""> {

  @Override
  protected BasicCallResult doInBackground(RequestFileInfo... params) {
   Log.d(TAG, "start doInBackground!"); 
   final RequestFileInfo req = params[0];
   ProgressValue progressValue = new ProgressValue(0, getString(R.string.msg_fetching_menu));
   publishProgress(progressValue);
   
   List<menux> menuxs ;
   menuxs = updateMenux();
   if (menuxs == null) {
    dismissDialog(DialogUtil.DIALOG_DOWNLAOD_IMAGE_PROGRESS); 
    return new BasicCallResult(
      "Can not get menu data! ", false); 
   }
   
   // 根据文件路径创建目录
   File basePath = new File(req.saveFilePath);
   if (!basePath.exists())
    basePath.mkdirs();
  
   int needDownloadImageCount = 0;//记录需要下载的图片数
   int finishDownloadImageCount = 0;//记录完成下载的图片数
   long startTime;
   long endTime;
   int length = 0;
   double totalLength = 0;
   int count = 0;
   
   class ImageInfo{
    public String imageName;
    public String imageMenuTypeGroupx;
    public HttpURLConnection conn;
   }
   List<imageinfo> imageInfos = new ArrayList<imageinfo>();
   
   //遍历菜品,取得需要下载的图片文件的总数量和能连接上的图片文件的总大小和信息
   for (Menux menux : menuxs) {
    try {
     String imageName = menux.getPicname();// 菜品图片名
     if (StringUtils.isNotEmpty(imageName)) {
      needDownloadImageCount += 1;
      URL url = new URL(req.fileParentUrl+ File.separator  
          + java.net.URLEncoder.encode(imageName,
            "UTF-8")); // 如果菜品名是中文,为了解决乱码问题,改变编码方式
      HttpURLConnection conn = (HttpURLConnection) url
        .openConnection();// throws IOException
      Log.i(TAG, "response code:" + conn.getResponseCode());
      if (HttpURLConnection.HTTP_OK == conn.getResponseCode()) {
       length += conn.getContentLength();
       String imageMenuTypeGroupx = menux.getMenutype() + menux.getGroupx();// 菜品分类
       
       ImageInfo imageInfo = new ImageInfo();
       imageInfo.imageName = imageName;
       imageInfo.imageMenuTypeGroupx = imageMenuTypeGroupx;
       imageInfo.conn = conn;
       imageInfos.add(imageInfo);
      }
     }
    }catch(IOException e){
     e.printStackTrace();
    }
   }
   
   if(imageInfos.size() == 0){
    return new BasicCallResult("No image need download! ", false);
   }
   totalLength = StringUtils.bytes2M(length);
   progressValue = new ProgressValue(0, getString(R.string.msg_start_download_menuimage));
   publishProgress(progressValue); 
   
   startTime = System.currentTimeMillis();
   
   // 遍历能够连接上的图片信息下载
   for (ImageInfo imageInfo : imageInfos) {
    try {
     /*
     String imageName = menux.getPicname();// 菜品图片名
     if (StringUtils.isNotEmpty(imageName)) { 
      String imageMenuTypeGroupx = menux.getMenutype()
        + menux.getGroupx();// 菜品分类
      URL url = new URL(req.fileParentUrl+ File.separator  
          + java.net.URLEncoder.encode(imageName,
            "UTF-8")); // 如果菜品名是中文,为了解决乱码问题,改变编码方式
      HttpURLConnection conn = (HttpURLConnection) url
        .openConnection();// throws IOException
      Log.i(TAG, "response code:" + conn.getResponseCode());
      if (HttpURLConnection.HTTP_OK == conn.getResponseCode()) {
      */
     String imageMenuTypeGroupx = imageInfo.imageMenuTypeGroupx;
     String imageName = imageInfo.imageName;
     InputStream is = imageInfo.conn.getInputStream();
       
       /*
        * 用这几种方式打开 is 都可以,用上面一种方式测试是否连接上,若连接上了,再做下载处理
        * 
       InputStream is = conn.getURL().openStream();
       InputStream is = url.openStream();
                            */
       
       // 根据菜品分类创建下一级目录
       File path;
       if (StringUtils.isNotEmpty(imageMenuTypeGroupx)) {
        path = new File(req.saveFilePath
          + File.separator + imageMenuTypeGroupx);
        if (!path.exists())
         path.mkdir();
       } else {
        path = new File(req.saveFilePath);
       }

       File imageFile = new File(path, imageName);
       FileOutputStream fos = new FileOutputStream(
         imageFile);
       //progressValue = new ProgressValue(0, " downloading:");
       byte buffer[] = new byte[1024];
       Log.d(TAG, "preper buffer!");
       finishDownloadImageCount += 1;
       do {
        int numread = is.read(buffer);    
        if (numread <= 0) {
         // publish end
         break;
        }
        count += numread;
        fos.write(buffer, 0, numread);
        Log.d(TAG, "start fos.write!");  
        
        endTime = System.currentTimeMillis();
        double currentLength = StringUtils.bytes2M(count); 
        double kbPerSecond = count * 1f / (endTime - startTime);//即时下载速度因精确到毫秒级的时间,
                                                                      //时间单位太大,会出现 endTime - startTime = 0 的情况,使得
                                                                      // kbPerSecond无限大,改为计算平均下载速度。完整表达式应为
                                                                      //(count / 1000f) / ((endTime - startTime) / 1000f),
                                                                      // b/ms = Kb/S   (b=byte)   
        double downloadTotalTime = (endTime - startTime) / 1000f;
        progressValue.message = String.format(
          "%d/%d\t\t%.2f M/%.2f M\t\t%.2fKb/S\t\t\t%.1f S ", finishDownloadImageCount, needDownloadImageCount,
          currentLength, totalLength, kbPerSecond, downloadTotalTime);
        progressValue.progress = (int) ((((float) count) / length) * DialogUtil.LONG_PROGRESS_MAX);
        publishProgress(progressValue);  

       } while (true);
       fos.flush();
       fos.close();
       is.close();
      //}
     } catch (MalformedURLException e) {
     e.printStackTrace();
     return new BasicCallResult("Wrong url! ", false);
      } catch (IOException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
     return new BasicCallResult("Error: "
       + e.getLocalizedMessage(), false);
    }
   }

   BasicCallResult callResult = new BasicCallResult(
     "download finish!", true);
   callResult.data = needDownloadImageCount + "";//int转String
   callResult.data2 = String.valueOf(finishDownloadImageCount);
   return callResult;
  }

  @Override
  protected void onPostExecute(BasicCallResult result) {
   if (result.ok) {
    Log.d(TAG, "download menu image success!"); 
    mProgressDialog.setMessage(getString(R.string.msg_download_image_success));
    //ToastUtils.showSuccess(getApplicationContext(), "congratulation!  download success!");
    if(Integer.parseInt(result.data) > Integer.parseInt(result.data2)){
     ToastUtils.showLong(getApplicationContext(),"needDownload:" + result.data + "   "
       + "finishDownload:" + result.data2 + "   "
       + "you should put all menu images to server");
    } 
   } else {
    Log.d(TAG, "download menu image failed!");
    ToastUtils.showFailure(getApplicationContext(), "5"
      + result.message);
   }
   
   DiSettings.putBoolean(getApplicationContext(),
     DiSettings.KEY_DOWNLOAD_MENU_IMAGE, false);
   
   dismissDialog(DialogUtil.DIALOG_DOWNLAOD_IMAGE_PROGRESS);
  }
  
  @Override
  protected void onProgressUpdate(ProgressValue... values) {   
            Log.d(TAG,values[0].toString());   
            mProgressDialog.setProgress(values[0].progress);   
            mProgressDialog.setMessage(values[0].message);
       }
   
 }
</imageinfo></imageinfo></menux></requestfileinfo></menux></menux>


相关文章
|
10月前
|
数据采集 Java API
Jsoup库能处理多线程下载吗?
Jsoup库能处理多线程下载吗?
|
10天前
|
开发者 Windows
NDM多线程下载器!实用的下载器,绿色版下载及安装教程
NDM是一款小巧高效的多线程下载器,支持Windows、Mac及浏览器插件,绿色单文件仅904KB,无需安装。已汉化,操作简单,下载速度快,支持HTTP/HTTPS/FTP协议,不支持磁力链接。使用前需关闭杀毒软件,配合7-ZIP解压,浏览器插件可自动嗅探音视频资源。
75 2
|
3月前
|
数据采集 存储 JSON
Python爬取知乎评论:多线程与异步爬虫的性能优化
Python爬取知乎评论:多线程与异步爬虫的性能优化
|
8月前
|
JavaScript 前端开发 Android开发
【03】仿站技术之python技术,看完学会再也不用去购买收费工具了-修改整体页面做好安卓下载发给客户-并且开始提交网站公安备案-作为APP下载落地页文娱产品一定要备案-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
【03】仿站技术之python技术,看完学会再也不用去购买收费工具了-修改整体页面做好安卓下载发给客户-并且开始提交网站公安备案-作为APP下载落地页文娱产品一定要备案-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
230 13
【03】仿站技术之python技术,看完学会再也不用去购买收费工具了-修改整体页面做好安卓下载发给客户-并且开始提交网站公安备案-作为APP下载落地页文娱产品一定要备案-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
|
3月前
|
存储 Android开发 数据安全/隐私保护
Thanox安卓系统增加工具下载,管理、阻止、限制后台每个APP运行情况
Thanox是一款Android系统管理工具,专注于权限、后台启动及运行管理。支持应用冻结、系统优化、UI自定义和模块管理,基于Xposed框架开发,安全可靠且开源免费,兼容Android 6.0及以上版本。
195 4
|
3月前
|
数据采集 监控 调度
干货分享“用 多线程 爬取数据”:单线程 + 协程的效率反超 3 倍,这才是 Python 异步的正确打开方式
在 Python 爬虫中,多线程因 GIL 和切换开销效率低下,而协程通过用户态调度实现高并发,大幅提升爬取效率。本文详解协程原理、实战对比多线程性能,并提供最佳实践,助你掌握异步爬虫核心技术。
|
3月前
|
存储 人工智能 文字识别
三款安卓手机word编辑器下载,Microsoft Word,wps office,Word手机版,手机word编辑查看阅读器,PDF转换器apk下载
WPS Office是一款功能强大的办公软件,支持文档编辑、表格处理和演示文稿制作,兼容多种格式并提供丰富的云服务。它具备低内存占用、快速运行的特点,支持跨设备同步与多人协作,内置海量模板及AI辅助功能,如智能写作和PPT自动生成。此外,还可扫描文件、编辑PDF并转换为其他格式,极大提升办公效率,适合手机用户便捷操作。
209 1
|
7月前
|
JavaScript Linux 网络安全
Termux安卓终端美化与开发实战:从下载到插件优化,小白也能玩转Linux
Termux是一款安卓平台上的开源终端模拟器,支持apt包管理、SSH连接及Python/Node.js/C++开发环境搭建,被誉为“手机上的Linux系统”。其特点包括零ROOT权限、跨平台开发和强大扩展性。本文详细介绍其安装准备、基础与高级环境配置、必备插件推荐、常见问题解决方法以及延伸学习资源,帮助用户充分利用Termux进行开发与学习。适用于Android 7+设备,原创内容转载请注明来源。
1394 77
|
8月前
|
JavaScript 搜索推荐 Android开发
【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
259 8
【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡

热门文章

最新文章