Android中如何java实现上传进度带进度的文件上传?Http可以java实现上传进度吗

君,已阅读到文档的结尾了呢~~
【doc】基于HTTP文件上传进度显示组件的设计及实现——所有资料文档均为本人悉心收集,全部是文档中的精品,绝对值得下载收藏!
扫扫二维码,随身浏览文档
手机或平板扫扫即可继续访问
【doc】基于HTTP文件上传进度显示组件的设计及实现
举报该文档为侵权文档。
举报该文档含有违规或不良信息。
反馈该文档无法正常浏览。
举报该文档为重复文档。
推荐理由:
将文档分享至:
分享完整地址
文档地址:
粘贴到BBS或博客
flash地址:
支持嵌入FLASH地址的网站使用
html代码:
&embed src='/DocinViewer-4.swf' width='100%' height='600' type=application/x-shockwave-flash ALLOWFULLSCREEN='true' ALLOWSCRIPTACCESS='always'&&/embed&
450px*300px480px*400px650px*490px
支持嵌入HTML代码的网站使用
您的内容已经提交成功
您所提交的内容需要审核后才能发布,请您等待!
3秒自动关闭窗口Android OkHttp文件上传与下载的进度监听扩展
来自csdn 安卓弟,另外okhttp的sample中有代码原型& &,可以对照此文相互参考。相信大家对OkHttp也是相当的熟悉了,毕竟是Square的东西,对于其种种优点,这里也不再叙说。优秀是优秀,但是毕竟优秀的东西给我们封装了太多,那么问题来了,我们使用OkHttp作为我们的网络层,简单地进行GET/POST请求是毫无问题。近日看了产品的设计稿,毛估估会有文件的上传与下载的需求,如果使用OkHttp作为网络层进行封装,你会惊讶的发现,简直封装的太“完美”了。如果现在有这么一个需求,要求对文件进行上传或下载,但是在上传或者下载前,你需要给用户一个友好的提示,在上传或者下载中,你需要将进度展示给用户,下载或者完成后提示用户下载完成。但是呢,找啊找,你会发现基本上找不到OkHttp的这种用法,百度是找不到,但是你别忘记了还有谷歌,谷歌一搜,Stackoverflow就全出来了,甚至github上的issue都出来了,可见并不是我们遇到了这么一个问题,还要许许多多的人遇到了这个问题,粗粗看了几个回答,感觉有几个还是比较靠谱的。为了日后的重用,我将其封装为一个OkHttp的扩展库,暂时取名为CoreProgress。要实现进度的监听,需要使用到OkHttp的依赖包Okio里的两个类,一个是Source,一个是Sink,至于Okio的东西,这里也不多说。
首先我们实现文件下载的进度监听。OkHttp给我们的只是一个回调,里面有Response返回结果,我们需要继承一个类,对结果进行监听,这个类就是ResponseBody,但是如何将它设置到OkHttp中去呢,答案是拦截器。拦截器的部分后面再叙述,这里先实现ResponseBody的子类ProgressResponseBody。要监听进度,我们必然需要一个监听器,也就是一个接口,在其实现类中完成回调内容的处理,该接口声明如下。/**
&*&响应体进度回调接口,比如用于文件下载中
&*&User:lizhangqu()
&*&Time:&17:16
public&interface&ProgressResponseListener&{
&&&&void&onResponseProgress(long&bytesRead,&long&contentLength,&boolean&done);
}然后会使用到该接口/**
&*&包装的响体,处理进度
&*&User:lizhangqu()
&*&Time:&17:18
public&class&ProgressResponseBody&extends&ResponseBody&{
&&&&//实际的待包装响应体
&&&&private&final&ResponseBody&responseB
&&&&//进度回调接口
&&&&private&final&ProgressResponseListener&progressL
&&&&//包装完成的BufferedSource
&&&&private&BufferedSource&bufferedS
&&&&&*&构造函数,赋值
&&&&&*&@param&responseBody&待包装的响应体
&&&&&*&@param&progressListener&回调接口
&&&&public&ProgressResponseBody(ResponseBody&responseBody,&ProgressResponseListener&progressListener)&{
&&&&&&&&this.responseBody&=&responseB
&&&&&&&&this.progressListener&=&progressL
&&&&&*&重写调用实际的响应体的contentType
&&&&&*&@return&MediaType
&&&&@Override&public&MediaType&contentType()&{
&&&&&&&&return&responseBody.contentType();
&&&&&*&重写调用实际的响应体的contentLength
&&&&&*&@return&contentLength
&&&&&*&@throws&IOException&异常
&&&&@Override&public&long&contentLength()&throws&IOException&{
&&&&&&&&return&responseBody.contentLength();
&&&&&*&重写进行包装source
&&&&&*&@return&BufferedSource
&&&&&*&@throws&IOException&异常
&&&&@Override&public&BufferedSource&source()&throws&IOException&{
&&&&&&&&if&(bufferedSource&==&null)&{
&&&&&&&&&&&&//包装
&&&&&&&&&&&&bufferedSource&=&Okio.buffer(source(responseBody.source()));
&&&&&&&&return&bufferedS
&&&&&*&读取,回调进度接口
&&&&&*&@param&source&Source
&&&&&*&@return&Source
&&&&private&Source&source(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);
&&&&&&&&&&&&&&&&//增加当前读取的字节数,如果读取完成了bytesRead会返回-1
&&&&&&&&&&&&&&&&totalBytesRead&+=&bytesRead&!=&-1&?&bytesRead&:&0;
&&&&&&&&&&&&&&&&//回调,如果contentLength()不知道长度,会返回-1
&&&&&&&&&&&&&&&&progressListener.onResponseProgress(totalBytesRead,&responseBody.contentLength(),&bytesRead&==&-1);
&&&&&&&&&&&&&&&&return&bytesR
&&&&&&&&&&&&}
&&&&&&&&};
}类似装饰器,我们对原始的ResponseBody&进行了一层包装。并在其读取数据的时候设置了回调,回调的接口由构造函数传入,此外构造函数还传入了原始的ResponseBody,当系统内部调用了ResponseBody&的source方法的时候,返回的便是我们包装后的Source。然后我们还重写了几个方法调用原始的ResponseBody对应的函数返回结果。同理既然下载是这样,那么上传也应该是这样,我们乘热打铁完成上传的部分,下载是继承ResponseBody&,上传就是继承RequestBody,同时也应该还有一个监听器。/**
&*&请求体进度回调接口,比如用于文件上传中
&*&User:lizhangqu()
&*&Time:&17:16
public&interface&ProgressRequestListener&{
&&&&void&onRequestProgress(long&bytesWritten,&long&contentLength,&boolean&done);
}RequestBody的子类实现类比ResponseBody&,基本上复制一下稍加修改即可使用。/**
&*&包装的请求体,处理进度
&*&User:lizhangqu()
&*&Time:&17:15
public&&class&ProgressRequestBody&extends&RequestBody&{
&&&&//实际的待包装请求体
&&&&private&final&RequestBody&requestB
&&&&//进度回调接口
&&&&private&final&ProgressRequestListener&progressL
&&&&//包装完成的BufferedSink
&&&&private&BufferedSink&bufferedS
&&&&&*&构造函数,赋值
&&&&&*&@param&requestBody&待包装的请求体
&&&&&*&@param&progressListener&回调接口
&&&&public&ProgressRequestBody(RequestBody&requestBody,&ProgressRequestListener&progressListener)&{
&&&&&&&&this.requestBody&=&requestB
&&&&&&&&this.progressListener&=&progressL
&&&&&*&重写调用实际的响应体的contentType
&&&&&*&@return&MediaType
&&&&@Override
&&&&public&MediaType&contentType()&{
&&&&&&&&return&requestBody.contentType();
&&&&&*&重写调用实际的响应体的contentLength
&&&&&*&@return&contentLength
&&&&&*&@throws&IOException&异常
&&&&@Override
&&&&public&long&contentLength()&throws&IOException&{
&&&&&&&&return&requestBody.contentLength();
&&&&&*&重写进行写入
&&&&&*&@param&sink&BufferedSink
&&&&&*&@throws&IOException&异常
&&&&@Override
&&&&public&void&writeTo(BufferedSink&sink)&throws&IOException&{
&&&&&&&&if&(bufferedSink&==&null)&{
&&&&&&&&&&&&//包装
&&&&&&&&&&&&bufferedSink&=&Okio.buffer(sink(sink));
&&&&&&&&//写入
&&&&&&&&requestBody.writeTo(bufferedSink);
&&&&&&&&//必须调用flush,否则最后一部分数据可能不会被写入
&&&&&&&&bufferedSink.flush();
&&&&&*&写入,回调进度接口
&&&&&*&@param&sink&Sink
&&&&&*&@return&Sink
&&&&private&Sink&sink(Sink&sink)&{
&&&&&&&&return&new&ForwardingSink(sink)&{
&&&&&&&&&&&&//当前写入字节数
&&&&&&&&&&&&long&bytesWritten&=&0L;
&&&&&&&&&&&&//总字节长度,避免多次调用contentLength()方法
&&&&&&&&&&&&long&contentLength&=&0L;
&&&&&&&&&&&&@Override
&&&&&&&&&&&&public&void&write(Buffer&source,&long&byteCount)&throws&IOException&{
&&&&&&&&&&&&&&&&super.write(source,&byteCount);
&&&&&&&&&&&&&&&&if&(contentLength&==&0)&{
&&&&&&&&&&&&&&&&&&&&//获得contentLength的值,后续不再调用
&&&&&&&&&&&&&&&&&&&&contentLength&=&contentLength();
&&&&&&&&&&&&&&&&}
&&&&&&&&&&&&&&&&//增加当前写入的字节数
&&&&&&&&&&&&&&&&bytesWritten&+=&byteC
&&&&&&&&&&&&&&&&//回调
&&&&&&&&&&&&&&&&progressListener.onRequestProgress(bytesWritten,&contentLength,&bytesWritten&==&contentLength);
&&&&&&&&&&&&}
&&&&&&&&};
}内部维护了一个原始的RequestBody&以及一个监听器,同样的也是由构造函数传入。当然也是要重写几个函数调用原始的RequestBody&对应的函数,文件的下载是read函数中进行监听的设置,毫无疑问文件的上传就是write函数了,我们在write函数中进行了类似的操作,并回调了接口中的函数。当系统内部调用了RequestBody&的writeTo函数时,我们对BufferedSink&进行了一层包装,即设置了进度监听,并返回了我们包装的BufferedSink&。于是乎,上传于下载的进度监听就完成了。还有一个重要的问题就是如何进行使用呢?如何进行使用呢?如何进行使用呢?重要的事要说三遍。我们还需要一个Helper类,对上传或者下载进行监听设置。文件的上传其实很简单,将我们的原始RequestBody和监听器&传入,返回我们的包装的ProgressRequestBody&,使用包装后的ProgressRequestBody&进行请求即可,但是文件的下载呢,OkHttp给我们返回的是Response,我们如何将我们包装的ProgressResponseBody设置进去呢,答案之前已经说过了,就是拦截器,具体见代码吧。/**
&*&进度回调辅助类
&*&User:lizhangqu()
&*&Time:&17:33
public&class&ProgressHelper&{
&&&&&*&包装OkHttpClient,用于下载文件的回调
&&&&&*&@param&client&待包装的OkHttpClient
&&&&&*&@param&progressListener&进度回调接口
&&&&&*&@return&包装后的OkHttpClient,使用clone方法返回
&&&&public&static&OkHttpClient&addProgressResponseListener(OkHttpClient&client,final&ProgressResponseListener&progressListener){
&&&&&&&&//克隆
&&&&&&&&OkHttpClient&clone&=&client.clone();
&&&&&&&&//增加拦截器
&&&&&&&&clone.networkInterceptors().add(new&Interceptor()&{
&&&&&&&&&&&&@Override
&&&&&&&&&&&&public&Response&intercept(Chain&chain)&throws&IOException&{
&&&&&&&&&&&&&&&&//拦截
&&&&&&&&&&&&&&&&Response&originalResponse&=&chain.proceed(chain.request());
&&&&&&&&&&&&&&&&//包装响应体并返回
&&&&&&&&&&&&&&&&return&originalResponse.newBuilder()
&&&&&&&&&&&&&&&&&&&&&&&&.body(new&ProgressResponseBody(originalResponse.body(),&progressListener))
&&&&&&&&&&&&&&&&&&&&&&&&.build();
&&&&&&&&&&&&}
&&&&&&&&});
&&&&&&&&return&
&&&&&*&包装请求体用于上传文件的回调
&&&&&*&@param&requestBody&请求体RequestBody
&&&&&*&@param&progressRequestListener&进度回调接口
&&&&&*&@return&包装后的进度回调请求体
&&&&public&static&ProgressRequestBody&addProgressRequestListener(RequestBody&requestBody,ProgressRequestListener&progressRequestListener){
&&&&&&&&//包装请求体
&&&&&&&&return&new&ProgressRequestBody(requestBody,progressRequestListener);
}对于文件下载的监听器我们为了不影响原来的OkHttpClient 实例,我们调用clone方法进行了克隆,之后对克隆的方法设置了响应拦截,并返回该克隆的实例。而文件的上传则十分简单,直接包装后返回即可。但是你别忘记了,我们的目的是在UI层进行回调,而OkHttp的所有请求都不在UI层。于是我们还要实现我们写的接口,进行UI操作的回调。由于涉及到消息机制,我们对之前的两个接口回调传的参数进行封装,封装为一个实体类便于传递。/**
&*&UI进度回调实体类
&*&User:lizhangqu()
&*&Time:&22:39
public&class&ProgressModel&implements&Serializable&{
&&&&//当前读取字节长度
&&&&private&long&currentB
&&&&//总字节长度
&&&&private&long&contentL
&&&&//是否读取完成
&&&&private&boolean&
&&&&public&ProgressModel(long&currentBytes,&long&contentLength,&boolean&done)&{
&&&&&&&&this.currentBytes&=&currentB
&&&&&&&&this.contentLength&=&contentL
&&&&&&&&this.done&=&
&&&&public&long&getCurrentBytes()&{
&&&&&&&&return&currentB
&&&&public&void&setCurrentBytes(long&currentBytes)&{
&&&&&&&&this.currentBytes&=&currentB
&&&&public&long&getContentLength()&{
&&&&&&&&return&contentL
&&&&public&void&setContentLength(long&contentLength)&{
&&&&&&&&this.contentLength&=&contentL
&&&&public&boolean&isDone()&{
&&&&&&&&return&
&&&&public&void&setDone(boolean&done)&{
&&&&&&&&this.done&=&
&&&&@Override
&&&&public&String&toString()&{
&&&&&&&&return&&ProgressModel{&&+
&&&&&&&&&&&&&&&&&currentBytes=&&+&currentBytes&+
&&&&&&&&&&&&&&&&&,&contentLength=&&+&contentLength&+
&&&&&&&&&&&&&&&&&,&done=&&+&done&+
&&&&&&&&&&&&&&&&'}';
}再实现我们的UI回调接口,对于文件的上传,我们需要实现的是ProgressRequestListener接口,文件的下载需要实现的是ProgressResponseListener接口,但是内部的逻辑处理是完全一样的。我们使用抽象类,提供一个抽象方法,该抽象方法用于UI层回调的处理,由具体开发去实现。涉及到消息机制就涉及到Handler类,在Handler的子类中维护一个弱引用指向外部类(用到了static防止内存泄露,但是需要调用外部类的一个非静态函数,所以将外部类引用直接由构造函数传入,在内部通过调用该引用的方法去实现),然后将主线程的Looper传入,调用父类构造函数。在onRequestProgress中发送进度更新的消息,在handleMessage函数中回调我们的抽象方法。我们只需要实现抽象方法,编写对应的UI更新代码即可。具体代码如下。/**
&*&请求体回调实现类,用于UI层回调
&*&User:lizhangqu()
&*&Time:&22:34
public&abstract&class&UIProgressRequestListener&implements&ProgressRequestListener&{
&&&&private&static&final&int&REQUEST_UPDATE&=&0x01;
&&&&//处理UI层的Handler子类
&&&&private&static&class&UIHandler&extends&Handler&{
&&&&&&&&//弱引用
&&&&&&&&private&final&WeakReference&UIProgressRequestListener&&mUIProgressRequestListenerWeakR
&&&&&&&&public&UIHandler(Looper&looper,&UIProgressRequestListener&uiProgressRequestListener)&{
&&&&&&&&&&&&super(looper);
&&&&&&&&&&&&mUIProgressRequestListenerWeakReference&=&new&WeakReference&UIProgressRequestListener&(uiProgressRequestListener);
&&&&&&&&@Override
&&&&&&&&public&void&handleMessage(Message&msg)&{
&&&&&&&&&&&&switch&(msg.what)&{
&&&&&&&&&&&&&&&&case&REQUEST_UPDATE:
&&&&&&&&&&&&&&&&&&&&UIProgressRequestListener&uiProgressRequestListener&=&mUIProgressRequestListenerWeakReference.get();
&&&&&&&&&&&&&&&&&&&&if&(uiProgressRequestListener&!=&null)&{
&&&&&&&&&&&&&&&&&&&&&&&&//获得进度实体类
&&&&&&&&&&&&&&&&&&&&&&&&ProgressModel&progressModel&=&(ProgressModel)&msg.
&&&&&&&&&&&&&&&&&&&&&&&&//回调抽象方法
&&&&&&&&&&&&&&&&&&&&&&&&uiProgressRequestListener.onUIRequestProgress(progressModel.getCurrentBytes(),&progressModel.getContentLength(),&progressModel.isDone());
&&&&&&&&&&&&&&&&&&&&}
&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&default:
&&&&&&&&&&&&&&&&&&&&super.handleMessage(msg);
&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&}
&&&&//主线程Handler
&&&&private&final&Handler&mHandler&=&new&UIHandler(Looper.getMainLooper(),&this);
&&&&@Override
&&&&public&void&onRequestProgress(long&bytesRead,&long&contentLength,&boolean&done)&{
&&&&&&&&//通过Handler发送进度消息
&&&&&&&&Message&message&=&Message.obtain();
&&&&&&&&message.obj&=&new&ProgressModel(bytesRead,&contentLength,&done);
&&&&&&&&message.what&=&REQUEST_UPDATE;
&&&&&&&&mHandler.sendMessage(message);
&&&&&*&UI层回调抽象方法
&&&&&*&@param&bytesWrite&当前写入的字节长度
&&&&&*&@param&contentLength&总字节长度
&&&&&*&@param&done&是否写入完成
&&&&public&abstract&void&onUIRequestProgress(long&bytesWrite,&long&contentLength,&boolean&done);
}另一个实现类代码雷同,不做叙述。/**
&*&请求体回调实现类,用于UI层回调
&*&User:lizhangqu()
&*&Time:&22:34
public&abstract&class&UIProgressResponseListener&implements&ProgressResponseListener&{
&&&&private&static&final&int&RESPONSE_UPDATE&=&0x02;
&&&&//处理UI层的Handler子类
&&&&private&static&class&UIHandler&extends&Handler&{
&&&&&&&&//弱引用
&&&&&&&&private&final&WeakReference&UIProgressResponseListener&&mUIProgressResponseListenerWeakR
&&&&&&&&public&UIHandler(Looper&looper,&UIProgressResponseListener&uiProgressResponseListener)&{
&&&&&&&&&&&&super(looper);
&&&&&&&&&&&&mUIProgressResponseListenerWeakReference&=&new&WeakReference&UIProgressResponseListener&(uiProgressResponseListener);
&&&&&&&&@Override
&&&&&&&&public&void&handleMessage(Message&msg)&{
&&&&&&&&&&&&switch&(msg.what)&{
&&&&&&&&&&&&&&&&case&RESPONSE_UPDATE:
&&&&&&&&&&&&&&&&&&&&UIProgressResponseListener&uiProgressResponseListener&=&mUIProgressResponseListenerWeakReference.get();
&&&&&&&&&&&&&&&&&&&&if&(uiProgressResponseListener&!=&null)&{
&&&&&&&&&&&&&&&&&&&&&&&&//获得进度实体类
&&&&&&&&&&&&&&&&&&&&&&&&ProgressModel&progressModel&=&(ProgressModel)&msg.
&&&&&&&&&&&&&&&&&&&&&&&&//回调抽象方法
&&&&&&&&&&&&&&&&&&&&&&&&uiProgressResponseListener.onUIResponseProgress(progressModel.getCurrentBytes(),&progressModel.getContentLength(),&progressModel.isDone());
&&&&&&&&&&&&&&&&&&&&}
&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&default:
&&&&&&&&&&&&&&&&&&&&super.handleMessage(msg);
&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&}
&&&&//主线程Handler
&&&&private&final&Handler&mHandler&=&new&UIHandler(Looper.getMainLooper(),&this);
&&&&@Override
&&&&public&void&onResponseProgress(long&bytesRead,&long&contentLength,&boolean&done)&{
&&&&&&&&//通过Handler发送进度消息
&&&&&&&&Message&message&=&Message.obtain();
&&&&&&&&message.obj&=&new&ProgressModel(bytesRead,&contentLength,&done);
&&&&&&&&message.what&=&RESPONSE_UPDATE;
&&&&&&&&mHandler.sendMessage(message);
&&&&&*&UI层回调抽象方法
&&&&&*&@param&bytesRead&当前读取响应体字节长度
&&&&&*&@param&contentLength&总字节长度
&&&&&*&@param&done&是否读取完成
&&&&public&abstract&void&onUIResponseProgress(long&bytesRead,&long&contentLength,&boolean&done);
}最简单的一步就是在我们的程序中使用了。为了方便Android Studio用户使用,我将其发布到了中央库。加入如下依赖即可dependencies&{
&&compile&'cn.edu.zafu:coreprogress:0.0.1'
}注意OkHttp的依赖需要自己手动添加,这个库中OkHttp只是编译时依赖,并没有打包进去。至于代码,也已经寄托在了github上,如果有bug,欢迎修正。,具体使用方法github上也已经贴出来了。如果依赖gradle不能下载的话可以直接从github上下代码。这里贴一个简单的例子,布局文件,两个进度条用于显示进度&LinearLayout&xmlns:android=&/apk/res/android&
&&&&&&&&&&&&&&xmlns:tools=&/tools&
&&&&&&&&&&&&&&android:layout_width=&match_parent&
&&&&&&&&&&&&&&android:layout_height=&match_parent&
&&&&&&&&&&&&&&android:orientation=&vertical&
&&&&&&&&&&&&&&tools:context=&.MainActivity&&
&&&&&ProgressBar
&&&&&&&&android:id=&@+id/upload_progress&
&&&&&&&&style=&?android:attr/progressBarStyleHorizontal&
&&&&&&&&android:layout_width=&match_parent&
&&&&&&&&android:layout_height=&wrap_content&
&&&&&&&&android:max=&100&
&&&&&&&&android:progress=&0&
&&&&&&&&/&
&&&&&Button
&&&&&&&&android:id=&@+id/upload&
&&&&&&&&android:layout_width=&match_parent&
&&&&&&&&android:layout_height=&wrap_content&
&&&&&&&&android:text=&Upload&/&
&&&&&ProgressBar
&&&&&&&&android:id=&@+id/download_progress&
&&&&&&&&style=&?android:attr/progressBarStyleHorizontal&
&&&&&&&&android:layout_width=&match_parent&
&&&&&&&&android:layout_height=&wrap_content&
&&&&&&&&android:max=&100&
&&&&&&&&android:progress=&0&
&&&&&&&&/&
&&&&&Button
&&&&&&&&android:id=&@+id/download&
&&&&&&&&android:layout_width=&match_parent&
&&&&&&&&android:layout_height=&wrap_content&
&&&&&&&&android:text=&Download&/&
&/LinearLayout&一个上传操作,一个下载操作,分别提供了UI层与非UI层回调的示例。最终代码中使用的监听器都是UI层的,因为我们要更新进度条。private&void&download()&{
&&&&&&&&//这个是非ui线程回调,不可直接操作UI
&&&&&&&&final&ProgressResponseListener&progressResponseListener&=&new&ProgressResponseListener()&{
&&&&&&&&&&&&@Override
&&&&&&&&&&&&public&void&onResponseProgress(long&bytesRead,&long&contentLength,&boolean&done)&{
&&&&&&&&&&&&&&&&Log.e(&TAG&,&&bytesRead:&&+&bytesRead);
&&&&&&&&&&&&&&&&Log.e(&TAG&,&&contentLength:&&+&contentLength);
&&&&&&&&&&&&&&&&Log.e(&TAG&,&&done:&&+&done);
&&&&&&&&&&&&&&&&if&(contentLength&!=&-1)&{
&&&&&&&&&&&&&&&&&&&&//长度未知的情况下回返回-1
&&&&&&&&&&&&&&&&&&&&Log.e(&TAG&,&(100&*&bytesRead)&/&contentLength&+&&%&done&);
&&&&&&&&&&&&&&&&}
&&&&&&&&&&&&&&&&Log.e(&TAG&,&&================================&);
&&&&&&&&&&&&}
&&&&&&&&};
&&&&&&&&//这个是ui线程回调,可直接操作UI
&&&&&&&&final&UIProgressResponseListener&uiProgressResponseListener&=&new&UIProgressResponseListener()&{
&&&&&&&&&&&&@Override
&&&&&&&&&&&&public&void&onUIResponseProgress(long&bytesRead,&long&contentLength,&boolean&done)&{
&&&&&&&&&&&&&&&&Log.e(&TAG&,&&bytesRead:&&+&bytesRead);
&&&&&&&&&&&&&&&&Log.e(&TAG&,&&contentLength:&&+&contentLength);
&&&&&&&&&&&&&&&&Log.e(&TAG&,&&done:&&+&done);
&&&&&&&&&&&&&&&&if&(contentLength&!=&-1)&{
&&&&&&&&&&&&&&&&&&&&//长度未知的情况下回返回-1
&&&&&&&&&&&&&&&&&&&&Log.e(&TAG&,&(100&*&bytesRead)&/&contentLength&+&&%&done&);
&&&&&&&&&&&&&&&&}
&&&&&&&&&&&&&&&&Log.e(&TAG&,&&================================&);
&&&&&&&&&&&&&&&&//ui层回调
&&&&&&&&&&&&&&&&downloadProgeress.setProgress((int)&((100&*&bytesRead)&/&contentLength));
&&&&&&&&&&&&&&&&//Toast.makeText(getApplicationContext(),&bytesRead&+&&&&&+&contentLength&+&&&&&+&done,&Toast.LENGTH_LONG).show();
&&&&&&&&&&&&}
&&&&&&&&};
&&&&&&&&//构造请求
&&&&&&&&final&Request&request1&=&new&Request.Builder()
&&&&&&&&&&&&&&&&.url(&http://121.41.119.107:81/test/1.doc&)
&&&&&&&&&&&&&&&&.build();
&&&&&&&&//包装Response使其支持进度回调
&&&&&&&&ProgressHelper.addProgressResponseListener(client,&uiProgressResponseListener).newCall(request1).enqueue(new&Callback()&{
&&&&&&&&&&&&@Override
&&&&&&&&&&&&public&void&onFailure(Request&request,&IOException&e)&{
&&&&&&&&&&&&&&&&Log.e(&TAG&,&&error&&,&e);
&&&&&&&&&&&&}
&&&&&&&&&&&&@Override
&&&&&&&&&&&&public&void&onResponse(Response&response)&throws&IOException&{
&&&&&&&&&&&&&&&&Log.e(&TAG&,&response.body().string());
&&&&&&&&&&&&}
&&&&&&&&});
&&&&private&void&upload()&{
&&&&&&&&File&file&=&new&File(&/sdcard/1.doc&);
&&&&&&&&//此文件必须在手机上存在,实际情况下请自行修改,这个目录下的文件只是在我手机中存在。
&&&&&&&&//这个是非ui线程回调,不可直接操作UI
&&&&&&&&final&ProgressRequestListener&progressListener&=&new&ProgressRequestListener()&{
&&&&&&&&&&&&@Override
&&&&&&&&&&&&public&void&onRequestProgress(long&bytesWrite,&long&contentLength,&boolean&done)&{
&&&&&&&&&&&&&&&&Log.e(&TAG&,&&bytesWrite:&&+&bytesWrite);
&&&&&&&&&&&&&&&&Log.e(&TAG&,&&contentLength&&+&contentLength);
&&&&&&&&&&&&&&&&Log.e(&TAG&,&(100&*&bytesWrite)&/&contentLength&+&&&%&done&&);
&&&&&&&&&&&&&&&&Log.e(&TAG&,&&done:&&+&done);
&&&&&&&&&&&&&&&&Log.e(&TAG&,&&================================&);
&&&&&&&&&&&&}
&&&&&&&&};
&&&&&&&&//这个是ui线程回调,可直接操作UI
&&&&&&&&final&UIProgressRequestListener&uiProgressRequestListener&=&new&UIProgressRequestListener()&{
&&&&&&&&&&&&@Override
&&&&&&&&&&&&public&void&onUIRequestProgress(long&bytesWrite,&long&contentLength,&boolean&done)&{
&&&&&&&&&&&&&&&&Log.e(&TAG&,&&bytesWrite:&&+&bytesWrite);
&&&&&&&&&&&&&&&&Log.e(&TAG&,&&contentLength&&+&contentLength);
&&&&&&&&&&&&&&&&Log.e(&TAG&,&(100&*&bytesWrite)&/&contentLength&+&&&%&done&&);
&&&&&&&&&&&&&&&&Log.e(&TAG&,&&done:&&+&done);
&&&&&&&&&&&&&&&&Log.e(&TAG&,&&================================&);
&&&&&&&&&&&&&&&&//ui层回调
&&&&&&&&&&&&&&&&uploadProgress.setProgress((int)&((100&*&bytesWrite)&/&contentLength));
&&&&&&&&&&&&&&&&//Toast.makeText(getApplicationContext(),&bytesWrite&+&&&&&+&contentLength&+&&&&&+&done,&Toast.LENGTH_LONG).show();
&&&&&&&&&&&&}
&&&&&&&&};
&&&&&&&&//构造上传请求,类似web表单
&&&&&&&&RequestBody&requestBody&=&new&MultipartBuilder().type(MultipartBuilder.FORM)
&&&&&&&&&&&&&&&&.addFormDataPart(&hello&,&&android&)
&&&&&&&&&&&&&&&&.addFormDataPart(&photo&,&file.getName(),&RequestBody.create(null,&file))
&&&&&&&&&&&&&&&&.addPart(Headers.of(&Content-Disposition&,&&form-&name=\&another\&;filename=\&another.dex\&&),&RequestBody.create(MediaType.parse(&application/octet-stream&),&file))
&&&&&&&&&&&&&&&&.build();
&&&&&&&&//进行包装,使其支持进度回调
&&&&&&&&final&Request&request&=&new&Request.Builder().url(&http://121.41.119.107:81/test/result.php&).post(ProgressHelper.addProgressRequestListener(requestBody,&uiProgressRequestListener)).build();
&&&&&&&&//开始请求
&&&&&&&&client.newCall(request).enqueue(new&Callback()&{
&&&&&&&&&&&&@Override
&&&&&&&&&&&&public&void&onFailure(Request&request,&IOException&e)&{
&&&&&&&&&&&&&&&&Log.e(&TAG&,&&error&&,&e);
&&&&&&&&&&&&}
&&&&&&&&&&&&@Override
&&&&&&&&&&&&public&void&onResponse(Response&response)&throws&IOException&{
&&&&&&&&&&&&&&&&Log.e(&TAG&,&response.body().string());
&&&&&&&&&&&&}
&&&&&&&&});
&&&&}需要特别注意的一点是文件的下载中如果文件大小未知,contentLength&会始终返回-1,对于已知文件大小的情况下,它返回的是实际文件大小。但是done只要在文件下载完成后才会返回true,可以使用两者的结合进行判断文件是否下载完成。当然,我们进行进度的监听,最终还是会回调内部的接口,如果请求成功会回调onResponse,请求失败则回调onFailure,我们可以在onResponse中处理最终的结果。比如提示用户上传完成或者下载完成等等 。还有一个细节需要注意就是连接的超时,读取与写入数据的超时时间的设置,在读取或者写入一些大文件的时候如果不设置这个参数可能会报异常,这里就随便设置了一下值,设得有点大,实际情况按需设置。//设置超时,不设置可能会报异常
&&&&private&void&initClient()&{
&&&&&&&&client.setConnectTimeout(1000,&TimeUnit.MINUTES);
&&&&&&&&client.setReadTimeout(1000,&TimeUnit.MINUTES);
&&&&&&&&client.setWriteTimeout(1000,&TimeUnit.MINUTES);
&&&&}文件的上传需要服务器的配合,为了证明PHP是世界上最好的语言,服务器的操作使用PHP大法,其实就是简单的输出POST的内容和文件的信息,并将一个文件保存到了服务器当前目录下的file文件夹下。&?php
//打印POST传递的参数
var_dump($_POST);
//打印文件信息
var_dump($_FILES);
//将文件保存到当前目录下的file文件夹下
move_uploaded_file($_FILES[&photo&][&tmp_name&],&&./file/&.$_FILES[&photo&][&name&]);
?&下面是运行结果,可以看到点击了上传或者下载后,进度条在不断更新。以及对应的日志输出。文件的上传,用数据说话文件的下载,同样是数据如果这篇文章对你有用,那么请点击下方的顶支持一个吧。源代码什么的就不再贴了,直接从github上下载吧
上一篇: 原文出处: http://blog.csdn.net/dantestones/article/details/ 注:这个ScrollView是自定义FrameLayout实现的,性能方面可能不如sdk中的ScrollView,但是这是一个学习自定义布局、自定义view、手势处理的实例教程。而且对于性能要求不高的场景,滚
下一篇: 原文: Bitesize Android KitKat: Week 6: Transitions Framework 注:本文的几个专用术语: transition 过渡动画 Scene 场景 这两个术语都有相应的类与之对应。 介绍 Android KitKat中让人兴奋的新增特性之一就是新的transitions 框架,它以声明的方式轻易

我要回帖

更多关于 android 图片上传进度 的文章

 

随机推荐