OkHttpClient httpClient = new OkHttpClient();
// mImgUrls为存放图片的url集合
MultipartBody.Builder builder = new MultipartBody.Builder().setType(MultipartBody.FORM);
if (Bimp.tempSelectBitmap != null) {
for (int i = 0; i < Bimp.tempSelectBitmap.size(); i++) {
ImageItem imageItem = Bimp.tempSelectBitmap.get(i);
File file = new File(imageItem.getImagePath());
if (file != null && file.exists()) {
builder.addFormDataPart("pic" + i, file.getName(), RequestBody.create(MediaType.parse("image/png"), file));
}
}
}
builder.addFormDataPart("classid", classId);
builder.addFormDataPart("notice_content", text);
builder.addFormDataPart("userno", userno);
builder.addFormDataPart("time", "" + time);
builder.addFormDataPart("sign", sign);
MultipartBody requestBody = builder.build();
//构建请求
Request request = new Request.Builder()
.url(Contacts.FABUDONGTAI)//地址
.post(requestBody)//添加请求体
.build();
httpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
Log.i("上传照片", "失败::" + e.getLocalizedMessage());
}
@Override
public void onResponse(Call call, Response response) throws IOException {
Log.i("上传照片", "成功::" + response.body().string());
}
});
package utils;
import android.os.Parcel;
import android.os.Parcelable;
/**
* Created by Administrator on 2017/1/19.
* func:上传进度的类
*/
public class FileUploadProgress implements Parcelable {
private long bytesWritten;//当前已上传的大小
private long contentLength;//需要上传的文件的总大小
private boolean done;//是否上传完成
public FileUploadProgress(long bytesWritten, long contentLength, boolean done) {
this.bytesWritten = bytesWritten;
this.contentLength = contentLength;
this.done = done;
}
public FileUploadProgress() {
}
public long getBytesWritten() {
return bytesWritten;
}
public void setBytesWritten(long bytesWritten) {
this.bytesWritten = bytesWritten;
}
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;
}
@Override
public String toString() {
return "FileUploadProgress{" +
"bytesWritten=" + bytesWritten +
", contentLength=" + contentLength +
", done=" + done +
'}';
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeLong(this.bytesWritten);
dest.writeLong(this.contentLength);
dest.writeByte(this.done ? (byte) 1 : (byte) 0);
}
protected FileUploadProgress(Parcel in) {
this.bytesWritten = in.readLong();
this.contentLength = in.readLong();
this.done = in.readByte() != 0;
}
public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
@Override
public FileUploadProgress createFromParcel(Parcel source) {
return new FileUploadProgress(source);
}
@Override
public FileUploadProgress[] newArray(int size) {
return new FileUploadProgress[size];
}
};
}
package utils;
/**
* Created by hcy on 2017/1/19.
*/
public interface OkhttpListener {
/**
* 上传进度的监听
*/
public interface ProgressRequestListener {
void onRequestProgress(FileUploadProgress progress);
}
}
package utils;
import java.io.IOException;
import okhttp3.MediaType;
import okhttp3.RequestBody;
import okio.Buffer;
import okio.BufferedSink;
import okio.ForwardingSink;
import okio.Okio;
import okio.Sink;
/**
* Created by hcy on 2017/1/19.
*/
public class ProgressRequestBody extends RequestBody {
//实际的待包装请求体
private final RequestBody requestBody;
//进度回调接口
private final OkhttpListener.ProgressRequestListener progressListener;
//包装完成的BufferedSink
private BufferedSink bufferedSink;
/**
* 构造函数,赋值
*
* @param requestBody 待包装的请求体
* @param progressListener 回调接口
*/
public ProgressRequestBody(RequestBody requestBody, OkhttpListener.ProgressRequestListener progressListener) {
this.requestBody = requestBody;
this.progressListener = progressListener;
}
/**
* 重写调用实际的响应体的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 += byteCount;
//回调
progressListener.onRequestProgress(new FileUploadProgress(bytesWritten, contentLength, bytesWritten == contentLength));
}
};
}
}
Request request = new Request.Builder()
.url(Contacts.FABUDONGTAI)//地址
.post(new ProgressRequestBody(requestBody, new OkhttpListener.ProgressRequestListener() {
@Override
public void onRequestProgress(FileUploadProgress progress) {
Log.i("上传照片进度::", progress.toString());
if (myHandler != null) {
Message msg = Message.obtain();
msg.what = 1;
msg.obj = progress;
myHandler.sendMessage(msg);
}
}
}))//添加请求体
.build();
package wytnewhttp;
import android.os.Parcel;
import android.os.Parcelable;
/**
* Created by hcy on 2017/3/10.
*/
public class FileDownLoadProgress implements Parcelable {
private long bytesDown;//当前已下载的大小
private long contentLength;//需要下载的文件的总大小
private boolean done;//是否下载完成
public FileDownLoadProgress() {
}
public FileDownLoadProgress(long bytesDown, long contentLength, boolean done) {
this.bytesDown = bytesDown;
this.contentLength = contentLength;
this.done = done;
}
public long getBytesDown() {
return bytesDown;
}
public void setBytesDown(long bytesDown) {
this.bytesDown = bytesDown;
}
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;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeLong(this.bytesDown);
dest.writeLong(this.contentLength);
dest.writeByte(this.done ? (byte) 1 : (byte) 0);
}
protected FileDownLoadProgress(Parcel in) {
this.bytesDown = in.readLong();
this.contentLength = in.readLong();
this.done = in.readByte() != 0;
}
public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
@Override
public FileDownLoadProgress createFromParcel(Parcel source) {
return new FileDownLoadProgress(source);
}
@Override
public FileDownLoadProgress[] newArray(int size) {
return new FileDownLoadProgress[size];
}
};
}
/**
* 下载进度的监听
*/
public interface ProgressResponseListener{
void onResponseProgress(FileDownLoadProgress progress);
}
package wytnewhttp;
import java.io.IOException;
import okhttp3.Interceptor;
import okhttp3.Response;
/**
* Created by hcy on 2017/3/10.
* func:监听下载进度的拦截器
*
*
*/
public class DownloadProgressInterceptor implements Interceptor {
private OkhttpListener.ProgressResponseListener listener;
public DownloadProgressInterceptor(OkhttpListener.ProgressResponseListener listener) {
this.listener = listener;
}
@Override
public Response intercept(Chain chain) throws IOException {
Response originalResponse = chain.proceed(chain.request());
return originalResponse.newBuilder()
.body(new ProgressResponseBody(originalResponse.body(), listener))
.build();
}
}
package wytnewhttp;
import java.io.IOException;
import okhttp3.MediaType;
import okhttp3.ResponseBody;
import okio.Buffer;
import okio.BufferedSource;
import okio.ForwardingSource;
import okio.Okio;
import okio.Source;
/**
* Created by hcy on 2017/3/10.
* func:下载进度监听
*/
public class ProgressResponseBody extends ResponseBody{
private final ResponseBody responseBody;
private final OkhttpListener.ProgressResponseListener progressResponseListener;
private BufferedSource bufferedSource;
public ProgressResponseBody(ResponseBody responseBody, OkhttpListener.ProgressResponseListener progressResponseListener) {
this.responseBody = responseBody;
this.progressResponseListener = progressResponseListener;
}
@Override
public MediaType contentType() {
return responseBody.contentType();
}
@Override
public long contentLength() {
return responseBody.contentLength();
}
@Override
public BufferedSource source() {
if (null == bufferedSource){
bufferedSource = Okio.buffer(source(responseBody.source()));
}
return bufferedSource;
}
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);
totalBytesRead += bytesRead != -1 ? bytesRead : 0;
progressResponseListener.onResponseProgress(new FileDownLoadProgress(totalBytesRead, responseBody.contentLength(), bytesRead == -1));
return bytesRead;
}
};
}
}
public static T downLoadFiles(final Class serviceClass, String endpoint, OkhttpListener.ProgressResponseListener responseListener) {
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(new DownloadProgressInterceptor(responseListener))
.retryOnConnectionFailure(true)
.connectTimeout(15, TimeUnit.SECONDS)
.build();
Retrofit adapter = new Retrofit.Builder()
.baseUrl(endpoint)
.client(client)
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
return adapter.create(serviceClass);
}
/**
* 下载大文件
*/
public interface DownLoadFile {
@Streaming //大文件
@GET
Observable downFile(@Url String fileUrl);
}
/**
*
* @param dirName 文件存放目录
* @param listener 进度监听
* @param fileType 文件后罪名
* @return 返回rxjava 回调
*/
public Observable downFile(final String dirName, OkhttpListener.ProgressResponseListener listener, final String fileType) {
return ServiceFactory.downLoadFiles(DownLoadFile.class, Contacts.AIYIXUE_TEACHER_URL, listener)
.downFile(url)
.subscribeOn(Schedulers.io())
.map(new Func1() {
@Override
public File call(ResponseBody responseBody) {
return ProjectUtils.writeResponseBodyToDisk(responseBody,dirName, ProjectUtils.md5Encode(url)+"."+fileType, context);
}
})
.observeOn(AndroidSchedulers.mainThread());
}
/**
* 下载文件的返回
* @param body 下载文件的返回体
* @param fileName 文件名: 001.ppt
* @param context 上下文
* @return 是否写入成功
*/
public static File writeResponseBodyToDisk(ResponseBody body,String dirName,String fileName,Context context) {
try {
File file = new File(getDiskCacheDir2(context,dirName)+File.separator+fileName);
InputStream inputStream = null;
OutputStream outputStream = null;
try {
byte[] fileReader = new byte[4096];
inputStream = body.byteStream();
outputStream = new FileOutputStream(file);
while (true) {
int read = inputStream.read(fileReader);
if (read == -1) {
break;
}
outputStream.write(fileReader, 0, read);
}
outputStream.flush();
return file;
} catch (IOException e) {
return null;
} finally {
if (inputStream != null) {
inputStream.close();
}
if (outputStream != null) {
outputStream.close();
}
}
} catch (IOException e) {
return null;
}
}
new WytHttpUtils(MainActivity.this,"uploadfile/ppt/2016112120083.pptx").downFile("ppt", new OkhttpListener.ProgressResponseListener() {
@Override
public void onResponseProgress(FileDownLoadProgress progress) {
Logger.t("文件下载进度").d(progress.getBytesDown()+"/"+progress.getContentLength()+"/"+progress.isDone());
}
},"pptx").subscribe(new Action1() {
@Override
public void call(File file) {
}
});
对于一些比较奇怪的接口
{{api_url}}{{version}}family-box/topics/item/{{topic_id}}?access_token={{access_token_parent1}}
//获取专题详情数据
@GET("family-box/topics/item/{topic_id}")
Flowable> requestProjectDetails(@Path("topic_id") int topic_id, @Query("access_token") String access_token);
注意啊:
Expected a string but was BEGIN_OBJECT
当我请求接口的时候,我只想把服务器返回的字符串打印出来,但出现了Expected a string but was BEGIN_OBJECT这个bug
明明我retrofit2加了
addConverterFactory(ScalarsConverterFactory.create())
但还是报错,这里注意下retrofit2初始化的顺序
retrofit = new Retrofit.Builder() .client(client) .baseUrl(BASE_URL) .addConverterFactory(ScalarsConverterFactory.create()) .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .build();
如果颠倒了就会出现这个问题。