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

来源:互联网 发布:net和java有什么区别 编辑:程序博客网 时间:2024/05/21 23:00

       上篇文章叙述了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  */ private List updateMenux() {  return mdb.findAll(); } /**  * 找出所有菜品数据  * 下载菜品图片类   * 遍历菜品数据List,根据每一个菜品图片名字拼出下载路径  * 多文件循环遍历单线程下载  *   * @author modify by ZX  *   */ private class DownlaodUpdateTask extends   AsyncTask {  @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 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 imageInfos = new ArrayList();      //遍历菜品,取得需要下载的图片文件的总数量和能连接上的图片文件的总大小和信息   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);       }    }