Android使用okhttp进行文件上传以及显示进度百分比

 博主介绍:本人专注于Android/java/数据库/微信小程序技术领域的开发,以及有好几年的计算机毕业设计方面的实战开发经验和技术积累;尤其是在安卓(Android)的app的开发和微信小程序的开发,很是熟悉和了解;本人也是多年的Android开发人员;希望我发布的此篇文件可以帮助到您;

效果演示

一、gradle配置

implementation 'com.squareup.okhttp3:okhttp:3.10.0'
implementation 'com.squareup.okio:okio:1.12.0'

二、文件上传代码

private void uploadFile(String fileInfor){
    File file = new File(fileInfor);
    String postUrl = Consts.URL + Consts.APP.MessageAction + "?action_flag=uploadFile";
    OkHttpUtil.postFile(postUrl, new ProgressListener() {
        @Override
        public void onProgress(long currentBytes, long contentLength, boolean done) {
            int progress = (int) (currentBytes * 100 / contentLength);      
            if(intentFlag==1){
                choiceImage.setText(imageName+"已上传"+progress+"%");
            }else{
                choiceVideo.setText(videoName+"已上传"+progress+"%");
            }
        }
    }, new Callback() {
        @Override
        public void onFailure(Call call, IOException e) {}
        @Override
        public void onResponse(Call call, Response response) throws IOException {
            if (response != null) {
                String result = response.body().string();           
            }
        }
    }, file);
}

三、对应的附属文件

1:ProgressListener
public interface ProgressListener {
    void onProgress(long currentBytes, long contentLength, boolean done);
}
2:ProgressModel
public class ProgressModel implements Parcelable {

    private long currentBytes;
    private long contentLength;
    private boolean done = false;

    public ProgressModel(long currentBytes, long contentLength, boolean done) {
        this.currentBytes = currentBytes;
        this.contentLength = contentLength;
        this.done = done;
    }

    public long getCurrentBytes() {
        return currentBytes;
    }

    public void setCurrentBytes(long currentBytes) {
        this.currentBytes = currentBytes;
    }

    public long getContentLength() {
        return contentLength;
    }

    public void setContentLength(long contentLength) {
        this.contentLength = contentLength;
    }

    public boolean isDone() {
        return done;
    }

    public void setDone(boolean done) {
        this.done = done;
    }

    private static final Creator<ProgressModel> CREATOR = new Creator<ProgressModel>() {
        @Override
        public ProgressModel createFromParcel(Parcel parcel) {
            return new ProgressModel(parcel);
        }

        @Override
        public ProgressModel[] newArray(int i) {
            return new ProgressModel[i];
        }
    };

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel parcel, int i) {
        parcel.writeLong(currentBytes);
        parcel.writeLong(contentLength);
        parcel.writeByte((byte) (done==true?1:0));
    }

    protected ProgressModel(Parcel parcel) {
        currentBytes = parcel.readLong();
        contentLength = parcel.readLong();
        done = parcel.readByte()!=0;
    }
}
3:ProgressRequestBody
public class ProgressRequestBody extends RequestBody {
    public static final int UPDATE = 0x01;
    private RequestBody requestBody;
    private ProgressListener mListener;
    private BufferedSink bufferedSink;
    private MyHandler myHandler;
    public ProgressRequestBody(RequestBody body, ProgressListener listener) {
        requestBody = body;
        mListener = listener;
        if (myHandler==null){
            myHandler = new MyHandler();
        }
    }

    class MyHandler extends Handler {

        public MyHandler() {
            super(Looper.getMainLooper());
        }

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what){
                case UPDATE:
                    ProgressModel progressModel = (ProgressModel) msg.obj;
                    if (mListener!=null)mListener.onProgress(progressModel.getCurrentBytes(),progressModel.getContentLength(),progressModel.isDone());
                    break;

            }
        }


    }

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

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

    @Override
    public void writeTo(BufferedSink sink) throws IOException {

        if (bufferedSink==null){
            bufferedSink = Okio.buffer(sink(sink));
        }
        //写入
        requestBody.writeTo(bufferedSink);
        //刷新
        bufferedSink.flush();
    }

    private Sink sink(BufferedSink sink) {

        return new ForwardingSink(sink) {
            long bytesWritten = 0L;
            long contentLength = 0L;
            @Override
            public void write(Buffer source, long byteCount) throws IOException {
                super.write(source, byteCount);
                if (contentLength==0){
                    contentLength = contentLength();
                }
                bytesWritten += byteCount;
                //回调
                Message msg = Message.obtain();
                msg.what = UPDATE;
                msg.obj =  new ProgressModel(bytesWritten,contentLength,bytesWritten==contentLength);
                myHandler.sendMessage(msg);
            }
        };
    }


}
4:ProgressResponseBody
public class ProgressResponseBody extends ResponseBody {
    public static final int UPDATE = 0x01;
    public static final String TAG = ProgressResponseBody.class.getName();
    private ResponseBody responseBody;
    private ProgressListener mListener;
    private BufferedSource bufferedSource;
    private Handler myHandler;
    public ProgressResponseBody(ResponseBody body, ProgressListener listener) {
        responseBody = body;
        mListener = listener;
        if (myHandler==null){
            myHandler = new MyHandler();
        }
    }

    /**
     * 将进度放到主线程中显示
     */
    class MyHandler extends Handler {

        public MyHandler() {
            super(Looper.getMainLooper());
        }

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what){
                case UPDATE:
                    ProgressModel progressModel = (ProgressModel) msg.obj;
                    //接口返回
                    if (mListener!=null)mListener.onProgress(progressModel.getCurrentBytes(),progressModel.getContentLength(),progressModel.isDone());
                    break;

            }
        }
    }

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

    @Override
    public long contentLength() {
        return responseBody.contentLength();
    }

    @Override
    public BufferedSource source() {

        if (bufferedSource==null){
            bufferedSource = Okio.buffer(mySource(responseBody.source()));
        }
        return bufferedSource;
    }

    private Source mySource(Source source) {

        return  new ForwardingSource(source) {
            long totalBytesRead = 0L;
            @Override
            public long read(Buffer sink, long byteCount) throws IOException {
                long bytesRead = super.read(sink, byteCount);
                totalBytesRead +=bytesRead!=-1?bytesRead:0;
                //发送消息到主线程
                Message msg = Message.obtain();
                msg.what = UPDATE;
                msg.obj =  new ProgressModel(totalBytesRead,contentLength(),totalBytesRead==contentLength());
                myHandler.sendMessage(msg);

                return bytesRead;
            }
        };


    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
要在 Android使用 OkHttp 实现带进度文件上传,可以使用 OkHttp 提供的 Interceptor 和 RequestBody 类。下面是一个简单的示例代码: ```java public class ProgressRequestBody extends RequestBody { private static final int DEFAULT_BUFFER_SIZE = 2048; private final File file; private final String contentType; private final ProgressListener listener; public ProgressRequestBody(File file, String contentType, ProgressListener listener) { this.file = file; this.contentType = contentType; this.listener = listener; } @Override public MediaType contentType() { return MediaType.parse(contentType); } @Override public long contentLength() { return file.length(); } @Override public void writeTo(BufferedSink sink) throws IOException { long fileLength = file.length(); byte[] buffer = new byte[DEFAULT_BUFFER_SIZE]; long uploaded = 0; try (InputStream in = new FileInputStream(file)) { int read; while ((read = in.read(buffer)) != -1) { uploaded += read; sink.write(buffer, 0, read); if (listener != null) { listener.onProgress(uploaded, fileLength); } } } } public interface ProgressListener { void onProgress(long uploaded, long total); } } ``` 这个类继承自 OkHttp 的 RequestBody 类,并实现了上传文件进度监听。在 writeTo() 方法中使用 InputStream 从文件中读取数据,并将数据写入 BufferedSink 中。同时,每次写入数据都会调用 onProgress() 方法通知进度监听器。 然后,创建一个 OkHttpClient,添加一个 Interceptor,该 Interceptor 使用 ProgressRequestBody 替换 RequestBody,从而实现进度监听: ```java OkHttpClient client = new OkHttpClient.Builder() .addInterceptor(new Interceptor() { @Override public Response intercept(Chain chain) throws IOException { Request original = chain.request(); // 使用 ProgressRequestBody 替换 RequestBody ProgressRequestBody requestBody = new ProgressRequestBody(file, contentType, listener); Request request = original.newBuilder() .method(original.method(), requestBody) .build(); return chain.proceed(request); } }) .build(); ``` 其中,file 是要上传的文件,contentType 是文件的 MIME 类型,listener 是进度监听器。最后,使用 OkHttpClient 发起一个上传文件的 Request: ```java Request request = new Request.Builder() .url(uploadUrl) .post(requestBody) .build(); Call call = client.newCall(request); call.enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { // 上传失败 } @Override public void onResponse(Call call, Response response) throws IOException { // 上传成功 } }); ``` 在 onResponse() 方法中处理上传结果即可。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Android毕业设计源码

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值