Android使用OKhttp分片上传

2,965 阅读1分钟

一、文件分片

public static byte[] getFileBlock(File file, long offset, int partSize) {
        byte[] result = new byte[partSize];
        RandomAccessFile accessFile = null;
        try {
            accessFile = new RandomAccessFile(file, "r");//只读mode
            accessFile.seek(offset);//文件光标位置
            //return the total number of bytes read into the buffer
            int readSize = accessFile.read(result);
            if (readSize == -1) {//文件结束
                return null;
            } else if (readSize == partSize) {
                return result;
            } else {
                byte[] readByte = new byte[readSize];
                System.arraycopy(result, 0, readByte, 0, readSize);
                return readByte;
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (accessFile != null) {
                    accessFile.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return result;
    }

二、构造RequestBody

getFileMime_Type(file) //获取文件的MimeType

//根据offset读取分片文件
byte[] partByte = FileUtils.getFileBlock(file, offset, partSize);
if (partByte == null) {
    return;
}
RequestBody requestBody = RequestBody.create(MediaType.parse(getFileMime_Type(file)), partByte);
MultipartBody.Builder mBuilder = new MultipartBody.Builder();
mBuilder.setType(MultipartBody.FORM).addFormDataPart("file", file.getName(), requestBody);

三、监听上传进度

需要重写RequestBody

public class FileProgressRequestBody extends RequestBody {

    private RequestBody mRequestBody;
    private FileProgressListener mProgressListener;

    public FileProgressRequestBody(MultipartBody requestBody, FileProgressListener progressListener) {
        this.mRequestBody = requestBody;
        this.mProgressListener = progressListener;
    }

    @Override
    public MediaType contentType() {
        return mRequestBody.contentType();
    }

    @Override
    public long contentLength() throws IOException {
        return mRequestBody.contentLength();
    }

    @Override
    public void writeTo(BufferedSink sink) throws IOException {
        CountingSink countingSink = new CountingSink(sink);
        BufferedSink bufferedSink = Okio.buffer(countingSink);
        mRequestBody.writeTo(bufferedSink);
        bufferedSink.flush();
    }

    private final class CountingSink extends ForwardingSink {

        private long contentLength;
        private int mCurrentLength;

        CountingSink(Sink delegate) {
            super(delegate);
            try {
                contentLength = contentLength();
                mCurrentLength = 0;
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void write(Buffer source, long byteCount) throws IOException {
            super.write(source, byteCount);
            mCurrentLength += byteCount;
            Log.e("FileProgress====", contentLength + " : " + mCurrentLength);
            if (mProgressListener != null) {
                mProgressListener.onProgress(contentLength, mCurrentLength);
            }
        }
    }
}

使用

FileProgressRequestBody multipartBody = new FileProgressRequestBody(mBuilder.build(), new FileProgressListener() {
      @Override
      public void onProgress(long contentLength, int current) {
          int progress = (int) (current * 1.0 / contentLength * 100);
          Log.i(TAG, "onProgress: " + progress);
      }
});