All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.avos.avoscloud.AVFileDownloader Maven / Gradle / Ivy

package com.avos.avoscloud;

import android.os.AsyncTask;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.concurrent.locks.Lock;

import okhttp3.Headers;
import okhttp3.Request;

/**
 * Created by wli on 15/12/22.
 * 文件下载,避免 AVFile 代码太多,所以从 AVFile 剥离出来
 * 下载的内容会存到本地
 * 流程:
 * 如果本地包含缓存,则直接返回缓存数据,否则从网络加载数据
 */
class AVFileDownloader extends AsyncTask {

  private final GetDataCallback dataCallback;
  private final GetDataStreamCallback dataStreamCallback;
  private final ProgressCallback progressCallback;
  private static final int READ_BUF_SIZE = 1024*8;

  private byte[] fileData;
  private InputStream is;

  public AVFileDownloader() {
    this.dataCallback = null;
    this.dataStreamCallback = null;
    this.progressCallback = null;
  }

  public AVFileDownloader(ProgressCallback progressCallback, GetDataCallback dataCallback) {
    this.dataCallback = dataCallback;
    this.dataStreamCallback = null;
    this.progressCallback = progressCallback;
  }

  public AVFileDownloader(ProgressCallback progressCallback, GetDataStreamCallback dataStreamCallback) {
    this.dataCallback = null;
    this.dataStreamCallback = dataStreamCallback;
    this.progressCallback = progressCallback;
  }

  protected AVException doWork(final String url) {
    fileData = null;
    if (!AVUtils.isBlankContent(url)) {
      File cacheFile = getCacheFile(url);
      if (cacheFile.exists()) {
        this.publishProgress(100);
        if (null != this.dataCallback) {
          fileData = AVPersistenceUtils.readContentBytesFromFile(cacheFile);
        } else if (null != this.dataStreamCallback) {
          try {
            is = AVPersistenceUtils.getInputStreamFromFile(cacheFile);
          } catch (IOException e) {
            LogUtil.log.e("failed to invoke doWork() url:" + url, e);
            is = null;
          }
        }
        return null;
      } else {
        return downloadFileFromNetwork(url);
      }
    } else {
      return new AVException(new IllegalArgumentException("url is null"));
    }
  }

  @Override
  protected AVException doInBackground(String... sUrl) {
    return doWork(sUrl[0]);
  }

  @Override
  protected void onProgressUpdate(Integer... progress) {
    super.onProgressUpdate(progress);
    if (progressCallback != null) {
      progressCallback.internalDone(progress[0], null);
    }
  }

  @Override
  protected void onPostExecute(AVException e) {
    super.onPostExecute(e);
    if (dataCallback != null) {
      dataCallback.internalDone(fileData, e);
    } else if (null != dataStreamCallback) {
      dataStreamCallback.internalDone0(this.is, e);
    }
  }

  /**
   * 根据 url 从网络下载文件
   * @param url
   * @return
   */
  private AVException downloadFileFromNetwork(final String url) {
    if (AVOSCloud.isDebugLogEnabled()) {
      LogUtil.avlog.d("downloadFileFromNetwork: " + url);
    }
    final File cacheFile = getCacheFile(url);

    final AVException[] errors = new AVException[1];
    Request.Builder requestBuilder = new Request.Builder();
    requestBuilder.url(url);

    AVHttpClient.ProgressListener listener = new AVHttpClient.ProgressListener() {
      @Override
      public void update(long bytesRead, long contentLength, boolean done) {
        publishProgress((int) (98 * bytesRead / (float) contentLength));
      }
    };
    AVHttpClient client = AVHttpClient.progressClientInstance(listener);
    client.execute(requestBuilder.build(), true, new AsyncHttpStreamResponseHandler() {

      @Override
      public void onSuccess(int statusCode, Headers headers, InputStream data) {
        if (statusCode / 100 == 2 && null != data) {
          // read data from InputStream and save to cache File
          byte[] content = new byte[READ_BUF_SIZE];

          Lock writeLock = AVPersistenceUtils.getLock(cacheFile.getAbsolutePath()).writeLock();
          FileOutputStream out = null;
          if (writeLock.tryLock()) {
            try {
              out = new FileOutputStream(cacheFile, false);
              int currentReadSize = data.read(content);
              while (currentReadSize > 0) {
                out.write(content, 0, currentReadSize);
                currentReadSize = data.read(content);
              }
            } catch (Exception e) {
              LogUtil.log.d(e.toString());
            } finally {
              try {
                data.close();
                if (out != null) {
                  out.close();
                }
              } catch (IOException e) {
                LogUtil.log.d(e.toString());
              }
              writeLock.unlock();
            }
          }
          if (null != dataCallback) {
            fileData = AVPersistenceUtils.readContentBytesFromFile(cacheFile);
          } else if (null != dataStreamCallback) {
            try {
              is = AVPersistenceUtils.getInputStreamFromFile(cacheFile);
            } catch (IOException e) {
              LogUtil.log.e("failed to invoke downloadFileFromNetwork() url:" + url, e);
              is = null;
            }
          }
        } else if (null != data) {
          errors[0] = new AVException(statusCode, "status code is invalid");
        } else {
          errors[0] = new AVException(statusCode, "data is empty!");
        }
      }

      @Override
      public void onFailure(int statusCode, Headers headers, Throwable error) {
        errors[0] = new AVException(error);
      }
    });
    this.publishProgress(100);
    return errors[0] != null ? errors[0] : null;
  }

  /**
   * 获取 url 对应的本地缓存文件
   *
   * @param url
   * @return
   */
  static File getCacheFile(String url) {
    return new File(getAVFileCachePath(), AVUtils.md5(url));
  }

  /**
   * 获取缓存的文件夹路径
   *
   * @return
   */
  static String getAVFileCachePath() {
    String fileCacheDir = AVPersistenceUtils.getCacheDir() + "/avfile/";
    File dirFile = new File(fileCacheDir);
    if (!dirFile.exists()) {
      dirFile.mkdirs();
    }
    return fileCacheDir;
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy