andorid http 多线程上传大文件

最近学习研究了下用http进行大文件上传:

经过不断修复优化,功能实现如下:
1.上传大文件;
2.实现多文件同时上传;
3.实现文件断点续传;
4.提供上传回调,显示上传速度与进度;
5.多线程上传,使用线程池进行管理;
6.上传失败保存现场,下回继续上传;
……..

直接贴代码,如有疑问请留言,参与讨论;

有三个核心类:ResumableUploadUtil ,UpLoadFileInfo,UploadTimerTask

ResumableUploadUtil 用于完成上传核心逻辑:

package upload;

import android.os.Handler;

import  upload.UpLoadFileInfo;
import  upload.ConstantValue;
import  upload.MyApplicationLike;
import  upload.ActivityStack;
import  upload.Logger;
import  upload.StringUtil;

import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.concurrent.Executors;


/**
 * Created by LiKang on 2016/12/22 15:15.
 * email:[email protected]
 */
public class ResumableUploadUtil {
    private final String Tag = "ResumableUploadUtil";
    private final String BOUNDARY = "----androidUploadBinBoundary";
    private Handler handler;
    /**
     * 默认分段大小
     */
    public final static long defaultChunkSize = 1024 * 1024 * 3 / 2;
    /**
     * 默认缓冲区大小
     */
    public final static int defaultBufferSize = 1024 * 4;
    /**
     * 默认并发上传线程数
     */
    public final static int defalutConcurrentThreadsNum = 3;

    private int concurrentThreadsNum = ResumableUploadUtil.defalutConcurrentThreadsNum;

    public ResumableUploadUtil() {
        this.handler = new Handler();
    }


    /**
     * 上传 准备;
     */
    private void upLoadPrepare(UpLoadFileInfo fileInfo) {
        computeChunkNums(fileInfo);
        computeEachThreadChunkNum(fileInfo);
    }

    /**
     * 计算分几片段;
     */
    private void computeChunkNums(UpLoadFileInfo fileInfo) {
        long tempLastChunkSize = fileInfo.fileSize % defaultChunkSize;
        fileInfo.totalChunks = (int) (fileInfo.fileSize / defaultChunkSize);
        if (tempLastChunkSize != 0) {
            fileInfo.totalChunks += 1;
        }
        Logger.d(Tag, "totalChunks:" + fileInfo.totalChunks);
    }

    /**
     * 设置 工作线程信息
     */
    private void computeEachThreadChunkNum(UpLoadFileInfo fileInfo) {
        int eachThreadChunkNum = fileInfo.totalChunks / concurrentThreadsNum; //每一个 线程承担的 上传片段
        int remainedChunkNum = fileInfo.totalChunks % concurrentThreadsNum;

        for (int threadIndex = 0; threadIndex < concurrentThreadsNum; threadIndex++) {
            HashMap<String, Integer> perThreadInfo = new HashMap<>();
            if (remainedChunkNum > threadIndex) {
                perThreadInfo.put("eachThreadChunkNum", eachThreadChunkNum + 1);
                perThreadInfo.put("endThreadChunkIndex", threadIndex * (eachThreadChunkNum + 1) + eachThreadChunkNum);
                perThreadInfo.put("curThreadChunkIndex", threadIndex * (eachThreadChunkNum + 1));
                perThreadInfo.put("startThreadChunkIndex", threadIndex * (eachThreadChunkNum + 1));
            } else {
                perThreadInfo.put("eachThreadChunkNum", eachThreadChunkNum);
                perThreadInfo.put("endThreadChunkIndex", threadIndex * eachThreadChunkNum + eachThreadChunkNum - 1 + remainedChunkNum);
                perThreadInfo.put("curThreadChunkIndex", threadIndex * eachThreadChunkNum + remainedChunkNum);
                perThreadInfo.put("startThreadChunkIndex", threadIndex * eachThreadChunkNum + remainedChunkNum);
            }
            perThreadInfo.put("threadId", threadIndex);
            fileInfo.threadInfo.add(perThreadInfo);
        }
        Logger.d(Tag, "fileInfo.threadInfo:" + fileInfo.threadInfo);
    }


    /**
     * 获取当前片段大小
     *
     * @return
     */
    private long getCurrentChunkSize(int curThreadChunkIndex, UpLoadFileInfo fileInfo) {
        long tempLastChunkSize = fileInfo.fileSize % defaultChunkSize;
        if (tempLastChunkSize != 0) {

            if (curThreadChunkIndex == fileInfo.totalChunks - 1) {
                //最后一片;
                return tempLastChunkSize;
            } else {
                return defaultChunkSize;
            }

        } else {
            return defaultChunkSize;
        }

    }

    /**
     * 重新计算当前上传大小;
     *
     * @return
     */
    private void recomputeHasUploadSize(UpLoadFileInfo fileInfo) {
        fileInfo.hasUploadSize = 0;
        fileInfo.hasUploadSizeBeforeOneSec = 0;
        for (int threadIndex = 0; threadIndex < concurrentThreadsNum; threadIndex++) {
            HashMap<String, Integer> perThreadInfo = fileInfo.threadInfo.get(threadIndex);
            int curThreadChunkIndex = perThreadInfo.get("curThreadChunkIndex");
            int startThreadChunkIndex = perThreadInfo.get("startThreadChunkIndex");
            for (int tempIndex = 0; tempIndex < curThreadChunkIndex - startThreadChunkIndex; tempIndex++) {
                fileInfo.hasUploadSize += getCurrentChunkSize(tempIndex, fileInfo);
            }
        }
    }

    /**
     * 开始或继续上传;
     *
     * @param fileInfo
     */
    public void startUpload(final UpLoadFileInfo fileInfo) {

        if (fileInfo.uploadStatus == UploadStatus.NOTSTART) {
            upLoadPrepare(fileInfo);
        } else {
            recomputeHasUploadSize(fileInfo);
        }
        fileInfo.uploadStatus = ResumableUploadUtil.UploadStatus.UPLOADING;
        fileInfo.fixedThreadPool = Executors.newFixedThreadPool(concurrentThreadsNum);
        fileInfo.isBecauseDoBackgroundPause = false;
        startCountTime(fileInfo);
        if (fileInfo.resumableUploadListener != null) {
            fileInfo.resumableUploadListener.onUpLoadStart(fileInfo);
        }

        //多线程上传;
        for (int threadIndex = 0; threadIndex < concurrentThreadsNum; threadIndex++) {
            HashMap<String, Integer> threadInfotemp = fileInfo.threadInfo.get(threadIndex);
            Integer eachThreadChunkNum = threadInfotemp.get("eachThreadChunkNum");
            Integer curThreadChunkIndex = threadInfotemp.get("curThreadChunkIndex");
            Integer endThreadChunkIndex = threadInfotemp.get("endThreadChunkIndex");
            Integer threadId = threadInfotemp.get("threadId");

            Logger.e(Tag, "threadId:" + threadId + "," + "eachThreadChunkNum:" + eachThreadChunkNum + "," + "curThreadChunkIndex:" + curThreadChunkIndex + "endThreadChunkIndex:" + endThreadChunkIndex);

            if (eachThreadChunkNum != 0) {
                doUpload(threadIndex, fileInfo);
            }
        }
    }

    /**
     * 上传暂停;
     *
     * @param becauseDoBackgroundPause 是否因为后台运行停止上传;
     * @param fileInfo
     */
    public void uploadPause(boolean becauseDoBackgroundPause, final UpLoadFileInfo fileInfo) {

        fileInfo.uploadStatus = ResumableUploadUtil.UploadStatus.PAUSE;
        fileInfo.isBecauseDoBackgroundPause = becauseDoBackgroundPause;
        stopCountTime(fileInfo);
        saveUploadFileInfo(fileInfo);
        if (fileInfo.resumableUploadListener != null) {
            handler.post(new Runnable() {
                @Override
                public void run() {
                    fileInfo.resumableUploadListener.onUpLoadPause(fileInfo);
                }
            });
        }
        if (fileInfo.fixedThreadPool != null) {
            fileInfo.fixedThreadPool.shutdownNow();
            fileInfo.fixedThreadPool = null;
        }
    }

    /**
     * 上传错误
     *
     * @param e        异常类别
     * @param fileInfo
     */
    public synchronized void uploadError(final Exception e, final UpLoadFileInfo fileInfo) {

        //上传失败;1. 保存上传现场; 2. 提示失败原因
        if (fileInfo.uploadStatus != UploadStatus.UPLOADING) {
            return;
        }
        Logger.d(Tag, "uploadError");
        fileInfo.uploadStatus = ResumableUploadUtil.UploadStatus.ERROR;
        if (fileInfo.resumableUploadListener != null) {
            handler.post(new Runnable() {
                @Override
                public void run() {

                    fileInfo.resumableUploadListener.onUpLoadError(e, fileInfo);
                }
            });
        }

        stopCountTime(fileInfo);
        saveUploadFileInfo(fileInfo);
        if (fileInfo.fixedThreadPool != null) {
            fileInfo.fixedThreadPool.shutdownNow();
            fileInfo.fixedThreadPool = null;
        }
    }

    /**
     * 上传成功
     *
     * @param fileInfo
     * @param url
     */
    private void uploadSuccess(final UpLoadFileInfo fileInfo, String url) {
        Logger.d(Tag, "任务上传成功!!!");
        fileInfo.uploadStatus = UploadStatus.SUCCESS;
        removeUploadFileInfo(fileInfo);
        stopCountTime(fileInfo);
        fileInfo.fileUrl = url;
        if (fileInfo.resumableUploadListener != null) {
            handler.post(new Runnable() {
                @Override
                public void run() {
                    fileInfo.resumableUploadListener.onUpLoadSuccess(fileInfo);

                }
            });
        }
        if (fileInfo.fixedThreadPool != null) {
            fileInfo.fixedThreadPool.shutdownNow();
            fileInfo.fixedThreadPool = null;
        }
    }

    /**
     * 保存上传文件记录
     *
     * @param fileInfo
     */
    public void saveUploadFileInfo(UpLoadFileInfo fileInfo) {
        String cacheFileExtension = "";
        if (fileInfo.fileType.equals(ConstantValue.FILETYPE_VIDEO)) {
            cacheFileExtension = ConstantValue.cacheVideoExtension;
        } else if (fileInfo.fileType.equals(ConstantValue.FILETYPE_DOC)) {
            cacheFileExtension = ConstantValue.cacheDocExtension;
        }
        fileInfo.cacheUploadFilePath = CacheUploadInfo.saveUploadInfoFile + File.separator
                + fileInfo.fileType + fileInfo.uploadFileId + "." + cacheFileExtension;
        Logger.d("cacheUploadFilePath", fileInfo.cacheUploadFilePath);
        CacheUploadInfo.writeObjectToFile(fileInfo, fileInfo.cacheUploadFilePath);
    }

    /**
     * 删除文件上传记录
     *
     * @param fileInfo
     */
    public void removeUploadFileInfo(UpLoadFileInfo fileInfo) {

        if (!StringUtil.isBlank(fileInfo.cacheUploadFilePath)) {
            File cacheUploadfile = new File(fileInfo.cacheUploadFilePath);
            if (cacheUploadfile.exists()) {
                cacheUploadfile.delete();
            }
        }
    }


    /**
     * 开启一个任务上传;
     *
     * @param threadIndex
     * @param fileInfo
     */
    private void doUpload(final int threadIndex, final UpLoadFileInfo fileInfo) {
        if (fileInfo.fixedThreadPool == null)
            return;

        if (!fileInfo.fixedThreadPool.isShutdown()) {
            fileInfo.fixedThreadPool.execute(
                    new Runnable() {
                        @Override
                        public void run() {
                            try {
                                byte[] headerInfo = buildHeaderInfo(threadIndex, fileInfo);
                                byte[] endInfo = ("\r\n--" + BOUNDARY + "--\r\n").getBytes("UTF-8");
                                HttpURLConnection conn = initHttpConnection(fileInfo.remoteUrl);
                                OutputStream out = conn.getOutputStream();
                                out.write(headerInfo);
                                writeToServer(threadIndex, conn, out, endInfo, fileInfo);//写数据;
                            } catch (Exception e) {
                                e.printStackTrace();
                                uploadError(e, fileInfo);

                            }
                        }
                    });
        }
    }


    /**
     * 构建上传参数;
     *
     * @param threadIndex
     * @param fileInfo
     * @return
     * @throws UnsupportedEncodingException
     */
    private byte[] buildHeaderInfo(int threadIndex, UpLoadFileInfo fileInfo) throws UnsupportedEncodingException {

        HashMap<String, String> params = new HashMap<>();
        params.put("cloudUserGUID", fileInfo.comParams.get("cloudUserGUID"));
        params.put("notifyUrl", fileInfo.uploadSuccessCallback);
        params.put("fileType", fileInfo.fileType);
        params.put("storageServerGUID", fileInfo.storageServerGUID);
        params.put("resumableType", "application/x-zip-compressed");
        params.put("resumableTotalSize", fileInfo.fileSize + "");
        params.put("resumableIdentifier", fileInfo.fileSize + "-" + fileInfo.fileName + "");
        params.put("resumableFilename", fileInfo.fileName + "");
        params.put("resumableRelativePath", fileInfo.filePath);
        params.put("resumableChunkSize", defaultChunkSize + "");   //分片大小;
        params.put("resumableTotalChunks", fileInfo.totalChunks + "");

        HashMap<String, Integer> perThreadInfo = fileInfo.threadInfo.get(threadIndex);
        int curThreadChunkIndex = perThreadInfo.get("curThreadChunkIndex");
        params.put("resumableCurrentChunkSize", getCurrentChunkSize(curThreadChunkIndex, fileInfo) + "");  //当前片大小
        params.put("resumableChunkNumber", curThreadChunkIndex + 1 + "");

        StringBuilder sb = new StringBuilder();
        for (String key : params.keySet()) {
            sb.append("--" + BOUNDARY + "\r\n");
            sb.append("Content-Disposition: form-data; name=\"" + key + "\""
                    + "\r\n");
            sb.append("\r\n");
            sb.append(params.get(key) + "\r\n");
        }

        //上传文件的头
        sb.append("--" + BOUNDARY + "\r\n");
        sb.append("Content-Disposition: form-data; name=\"file\"; filename=\"" + fileInfo.fileName + "\"" + "\r\n");
        sb.append("Content-Type: application/octet-stream" + "\r\n");
        sb.append("\r\n");

//        Logger.d(Tag, "headerInfo:" + sb.toString());
        Logger.d("buildHeaderInfo", "threadIndex:" + threadIndex + ",resumableTotalSize:"
                + fileInfo.fileSize + ",resumableTotalChunks:"
                + fileInfo.totalChunks + ",resumableCurrentChunkSize:"
                + getCurrentChunkSize(curThreadChunkIndex, fileInfo) + ",resumableChunkNumber" + (curThreadChunkIndex + 1) + "");

        byte[] haderInfoBytes = sb.toString().getBytes("UTF-8");
        params = null;
        sb = null;
        return haderInfoBytes;
    }

    /**
     * 初始化 http连接
     *
     * @param url
     * @return
     * @throws IOException
     */
    private HttpURLConnection initHttpConnection(URL url) throws IOException {
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod("POST");
        conn.setRequestProperty("Content-Type",
                "multipart/form-data; boundary=" + BOUNDARY);

        conn.setConnectTimeout(30 * 1000);//设置0.5min 超时
        conn.setRequestProperty("Connection", "Keep-Alive");
        conn.setRequestProperty("Charset", "UTF-8");
        conn.setDoInput(true);
        conn.setUseCaches(false);
        conn.setDoOutput(true);
        return conn;
    }


    //写每一个片段数据
    public void writeToServer(int threadIndex, HttpURLConnection conn, OutputStream out, byte[] endInfo, final UpLoadFileInfo fileInfo) throws Exception {
        RandomAccessFile raf = new RandomAccessFile(new File(fileInfo.filePath), "r");//负责读取数据
        float filesize = fileInfo.fileSize;
        HashMap<String, Integer> perThreadInfo = fileInfo.threadInfo.get(threadIndex);
        int curThreadChunkIndex = perThreadInfo.get("curThreadChunkIndex");

        raf.seek(defaultChunkSize * curThreadChunkIndex);
        byte b[] = new byte[defaultBufferSize];//暂存容器
        int n = 0; //本次写出字节数
        long readLength = 0;//记录此片已读字节数

        while (readLength < getCurrentChunkSize(curThreadChunkIndex, fileInfo)) {
            //判断是否在后台运行
            boolean runningOnBackground = ActivityStack.isRunningOnBackground(MyApplicationLike.getContext());
            if (runningOnBackground) {
                uploadPause(true, fileInfo);
            }
            if (fileInfo.uploadStatus != UploadStatus.UPLOADING) {
                return;
            }
            n = raf.read(b, 0, defaultBufferSize);
            out.write(b, 0, n);
            readLength += n;
            fileInfo.hasUploadSize += n;
            fileInfo.updateTextProgress();
            fileInfo.uploadProgress = (fileInfo.hasUploadSize / filesize) * 100;
            Logger.d(Tag, "进度:" + fileInfo.uploadProgress + "%" + ",hasUploadSize:" + fileInfo.hasUploadSize + ",filesize:" + filesize);

            if (fileInfo.resumableUploadListener != null) {
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        if (fileInfo.uploadStatus == UploadStatus.UPLOADING) {
                            fileInfo.resumableUploadListener.onUpLoading(fileInfo);
                        }
                    }
                });
            }
        }
        out.write(endInfo);
        out.close();
        raf.close();
        //工作线程;
        raf = null;
        b = null;
        handleWriterResult(threadIndex, conn, fileInfo);

    }

    /**
     * 处理每一片上传结果
     *
     * @param threadIndex
     * @param conn
     * @param fileInfo
     * @throws Exception
     */
    private void handleWriterResult(int threadIndex, HttpURLConnection conn, final UpLoadFileInfo fileInfo) throws Exception {
        //response:
        final String responseMsg = getResponseMsg(conn);
        Logger.d(Tag, "responseMsg:" + responseMsg);
        //response:==================
        HashMap<String, Integer> perThreadInfo = fileInfo.threadInfo.get(threadIndex);
        int curThreadChunkIndex = perThreadInfo.get("curThreadChunkIndex");
        int eachThreadChunkNum = perThreadInfo.get("eachThreadChunkNum");
        int startThreadChunkIndex = perThreadInfo.get("startThreadChunkIndex");
        int endThreadChunkIndex = perThreadInfo.get("endThreadChunkIndex");


        if (curThreadChunkIndex != endThreadChunkIndex) {

            //非最后一段
            if (conn.getResponseCode() == 200) {
                //继续上传
                Logger.d("handle2WriterResult", "handleWriterResult: " + ",threadIndex:" + threadIndex +
                        " ,CurrentChunkSize:" + getCurrentChunkSize(curThreadChunkIndex, fileInfo) +
                        ",curThreadChunkIndex:" + curThreadChunkIndex +
                        ",eachThreadChunkNum:" + eachThreadChunkNum +
                        ",startThreadChunkIndex:" + startThreadChunkIndex +
                        ",endThreadChunkIndex:" + endThreadChunkIndex +
                        ",totalChunks:" + fileInfo.totalChunks);
                Logger.d(Tag, "工作线程:" + threadIndex + "上传成功" + ",curThreadChunkIndex:" + curThreadChunkIndex);
                if (curThreadChunkIndex < endThreadChunkIndex) {
                    curThreadChunkIndex += 1;//每个工作线程的当前 片
                    perThreadInfo.put("curThreadChunkIndex", curThreadChunkIndex);
                }

                doUpload(threadIndex, fileInfo);
                Logger.d(Tag, "继续上传!!!");
            } else {
                uploadError(null, fileInfo);
            }

        } else {

            //最后一段
            if (conn.getResponseCode() == 200) {
                //上传成功
                Logger.d("handle2WriterResult", "handleWriterResult: " + ",threadIndex:" + threadIndex +
                        " ,CurrentChunkSize:" + getCurrentChunkSize(curThreadChunkIndex, fileInfo) +
                        ",curThreadChunkIndex:" + curThreadChunkIndex +
                        ",eachThreadChunkNum:" + eachThreadChunkNum +
                        ",startThreadChunkIndex:" + startThreadChunkIndex +
                        ",endThreadChunkIndex:" + endThreadChunkIndex +
                        ",totalChunks:" + fileInfo.totalChunks);
                Logger.d(Tag, "工作线程:" + threadIndex + "上传成功最后一段!!!");
                if (curThreadChunkIndex < endThreadChunkIndex) {
                    curThreadChunkIndex += 1;//每个工作线程的当前 片
                    perThreadInfo.put("curThreadChunkIndex", curThreadChunkIndex);
                }

                if (!StringUtil.isBlank(responseMsg)) {
                    JSONObject object = new JSONObject(responseMsg);
                    final String url = String.valueOf(object.get("data"));

                    if (!StringUtil.isBlank(url)) {
                        uploadSuccess(fileInfo, url);
                    }
                    object = null;
                }
            } else {
                uploadError(null, fileInfo);
            }
        }

    }


    /**
     * 获取到每一片 上传后结果
     *
     * @param conn
     * @return
     * @throws IOException
     */
    private String getResponseMsg(HttpURLConnection conn) throws IOException {
        StringBuilder sbResponse = new StringBuilder();
        BufferedReader in = new BufferedReader(new InputStreamReader(conn
                .getInputStream(), "UTF-8"));
        String inputLine;
        while ((inputLine = in.readLine()) != null) {
            sbResponse.append(inputLine);
        }
        in.close();
        String responseMsg = sbResponse.toString();
        in = null;
        sbResponse = null;
        return responseMsg;
    }

    public void startCountTime(UpLoadFileInfo fileInfo) {
        if (fileInfo.timerTask == null) {
            fileInfo.timerTask = new UploadTimerTask(fileInfo);
        }
        fileInfo.timerTask.start();
    }

    public void stopCountTime(UpLoadFileInfo fileInfo) {
        if (fileInfo.timerTask != null) {
            fileInfo.timerTask.stop();
        }
    }

    public enum UploadStatus {
        UPLOADING, SUCCESS, PAUSE, NOTSTART, ERROR
    }

    public interface ResumableUploadListener {

        void onUpLoading(UpLoadFileInfo fileInfo);

        void onUpLoadSuccess(UpLoadFileInfo fileInfo);

        void onUpLoadError(Exception e, UpLoadFileInfo fileInfo);

        void onUpLoadStart(UpLoadFileInfo fileInfo);

        void onUpLoadPause(UpLoadFileInfo fileInfo);

    }

    public void setResumableUploadListener(ResumableUploadUtil.ResumableUploadListener listener, UpLoadFileInfo fileInfo) {
        fileInfo.resumableUploadListener = listener;
    }

}

UpLoadFileInfo 用于保存上传记录:


package upload;

import upload.ResumableUploadUtil;
import upload.UploadTimerTask;
import upload.StringUtil;

import java.io.Serializable;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.ExecutorService;

import static upload.StringUtil.getDataSize;


public class UpLoadFileInfo implements Serializable {
    public URL remoteUrl;//上传地址
    public String fileUrl;//上传成功后文件地址
    public String fileName;
    public String filePath;
    public String cacheUploadFilePath;
    public long fileSize;
    public long hasUploadSize;
    public long hasUploadSizeBeforeOneSec;
    public long ModifiedDate;
    public long dbId; // id in the database, if is from database
    public float uploadProgress;
    public String uploadFileId;
    public int recLen = 0;//已经上传时间
    public HashMap<String, String> comParams;
    public String rootDir;
    public String storageServerGUID;
    public String uploadSuccessCallback;
    public String fileType;
    public String extension;
    public String textProgress = updateTextProgress();
    public String uploadSpeed = updateUploadSpeed();
    public boolean isBecauseDoBackgroundPause = false;
    public int totalChunks = 0;
    public transient UploadTimerTask timerTask;
    public transient ExecutorService fixedThreadPool;
    /**
     * 上传监听
     */
    public transient ResumableUploadUtil.ResumableUploadListener resumableUploadListener;
    /**
     * 上传状态
     */
    public ResumableUploadUtil.UploadStatus uploadStatus = ResumableUploadUtil.UploadStatus.NOTSTART;

    /**
     * 工作线程信息
     */
    public List<HashMap<String, Integer>> threadInfo = new ArrayList<>();


    public String updateTextProgress() {
        return textProgress = StringUtil.getDataSize(hasUploadSize) + "/" + StringUtil.getDataSize(fileSize);
    }


    public String updateUploadSpeed() {
        return uploadSpeed = getDataSize(hasUploadSize - hasUploadSizeBeforeOneSec) + "/s";
    }


    @Override
    public String toString() {
        return "UpLoadFileInfo{" +
                "UploadTimerTask=" + timerTask +
                ", remoteUrl=" + remoteUrl +
                ", fileUrl='" + fileUrl + '\'' +
                ", fileName='" + fileName + '\'' +
                ", filePath='" + filePath + '\'' +
                ", cacheUploadFilePath='" + cacheUploadFilePath + '\'' +
                ", fileSize=" + fileSize +
                ", hasUploadSize=" + hasUploadSize +
                ", ModifiedDate=" + ModifiedDate +
                ", dbId=" + dbId +
                ", uploadProgress=" + uploadProgress +
                ", uploadFileId=" + uploadFileId +
                ", recLen=" + recLen +
                ", comParams=" + comParams +
                ", rootDir='" + rootDir + '\'' +
                ", storageServerGUID='" + storageServerGUID + '\'' +
                ", uploadSuccessCallback='" + uploadSuccessCallback + '\'' +
                ", fileType='" + fileType + '\'' +
                ", extension='" + extension + '\'' +
                ", textProgress='" + textProgress + '\'' +
                ", uploadSpeed='" + uploadSpeed + '\'' +
                ", fixedThreadPool=" + fixedThreadPool +
                ", resumableUploadListener=" + resumableUploadListener +
                ", uploadStatus=" + uploadStatus +
                ", totalChunks=" + totalChunks +
                ", isBecauseDoBackgroundPause=" + isBecauseDoBackgroundPause +
                ", threadInfo=" + threadInfo +
                '}';
    }

}

UploadTimerTask 用于计时,计算上传速度:

package upload;

import android.os.SystemClock;

import upload.UpLoadFileInfo;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class UploadTimerTask {
    private UpLoadFileInfo upLoadFileInfo;
    private boolean stop = true;
    private ExecutorService executorService = Executors.newSingleThreadExecutor();

    public UploadTimerTask(UpLoadFileInfo upLoadFileInfo) {
        this.upLoadFileInfo = upLoadFileInfo;
    }


    public void start() {
        this.stop = false;
        executorService.execute(
                new Runnable() {
                    @Override
                    public void run() {
                        while (!stop) {
                            upLoadFileInfo.hasUploadSizeBeforeOneSec = upLoadFileInfo.hasUploadSize;
                            SystemClock.sleep(1000);
                            upLoadFileInfo.recLen++;
                            upLoadFileInfo.updateUploadSpeed();
                        }
                    }
                }
        );
    }

    public void stop() {
        this.stop = true;
    }
}

猜你喜欢

转载自blog.csdn.net/qq_17827919/article/details/71159077