Rxjava+Retrofit2+Okhttp3多文件上传(服务器端代码+客户端代码)
所有代码亲测可用,如有问题,欢迎指正。
首先在ApiService接口文件中新建文件上传接口
public interface ApiService {
static final String BASE_URL=" http://192.168.3.102:8080/";
/**
* 上传多头像
*/
@Multipart
@POST("wzly/uploadImg")
Observable<String> uploadMemberIcon(@Part List<MultipartBody.Part> partList);
}
我使用ServiceFactory.java封装了Retrofit2和OkHttp
package com.wzly.iscan.tools.api; import android.util.Log; import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.Locale;
import java.util.concurrent.TimeUnit; import okhttp3.FormBody;
import okhttp3.Interceptor;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory; /**
* Created by admin on 2016/11/15.
* 单例模式:每次实例化出来的都是统一个实例。
*/ public class ServiceFactory {
private final Gson mGsonDateFormat; public ServiceFactory() {
mGsonDateFormat = new GsonBuilder()
.setDateFormat("yyyy-MM-dd hh:mm:ss")
.create();
} private static class SingletonHolder {
private static final ServiceFactory INSTANCE = new ServiceFactory();
} public static ServiceFactory getInstance() {
return SingletonHolder.INSTANCE;
} /**
* create a service
*
* @param serviceClass
* @param <S>
* @return
*/
public <S> S createService(Class<S> serviceClass) {
String baseUrl = "";
try {
Field field1 = serviceClass.getField("BASE_URL");
baseUrl = (String) field1.get(serviceClass);
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.getMessage();
e.printStackTrace();
}
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.client(getOkHttpClient())
.addConverterFactory(GsonConverterFactory.create(mGsonDateFormat))
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
return retrofit.create(serviceClass);
} private final static long DEFAULT_TIMEOUT = 10; private OkHttpClient getOkHttpClient() {
//定制OkHttp
OkHttpClient.Builder httpClientBuilder = new OkHttpClient
.Builder();
//设置超时时间
httpClientBuilder.connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS);
httpClientBuilder.writeTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS);
httpClientBuilder.readTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS); httpClientBuilder.addInterceptor(new RequestInterceptor());
httpClientBuilder.addInterceptor(new LogInterceptor()); return httpClientBuilder.build();
} /**
* 日志拦截器
*/
private class LogInterceptor implements Interceptor {
@Override
public okhttp3.Response intercept(Chain chain) throws IOException {
long t1 = System.nanoTime();
okhttp3.Response response = chain.proceed(chain.request());
long t2 = System.nanoTime();
Log.v("zcb", String.format(Locale.getDefault(), "Received response for %s in %.1fms%n%s",
response.request().url(), (t2 - t1) / 1e6d, response.headers()));
okhttp3.MediaType mediaType1 = response.body().contentType();
String content = response.body().string();
Log.i("zcb", "response body:" + content);
return response.newBuilder()
.body(okhttp3.ResponseBody.create(mediaType1, content))
.build();
}
} /**
* 请求拦截器,修改请求header
*/
private class RequestInterceptor implements Interceptor{ @Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request()
.newBuilder()
.build();
Log.v("zcb", "request:" + request.toString());
Log.v("zcb", "request headers:" + request.headers().toString()); return chain.proceed(request);
}
} }
此外也用HttpResultSubscriber.java封装了Subscriber,代码如下:
package com.wzly.iscan.tools.api; import retrofit2.adapter.rxjava.HttpException;
import rx.Subscriber; /**
* Created by zcb
* Date:2016/7/27
* Time:21:27
*/
public abstract class HttpResultSubscriber<T> extends Subscriber<T> { @Override
public void onCompleted() { } @Override
public void onNext(T t) {
onSuccess(t);
} @Override
public void onError(Throwable e) {
e.printStackTrace();
//在这里做全局的错误处理
if (e instanceof HttpException) {
// ToastUtils.getInstance().showToast(e.getMessage());
}
_onError(e);
} public abstract void onSuccess(T t); public abstract void _onError(Throwable e);
}
接下来是多文件上传的关键代码:
public void uploadAvatarImg(String urlpath,String fileName,String sign) {
List<String> imgList=new ArrayList<String>();
imgList.add(urlpath);
MultipartBody.Builder builder=new MultipartBody.Builder()
.setType(MultipartBody.FORM) //表单类型
.addFormDataPart("imgfile","avatar.jpg")
.addFormDataPart("sign",APPConfig.serverSign);
//多张图
for (int i=0;i<imgList.size();i++){
File file=new File(imgList.get(i));
RequestBody requestBody=RequestBody.create(MediaType.parse("multipart/form-data"),file);
builder.addFormDataPart("imgfile"+i,file.getName(),requestBody);//"imgfile"+i 后台接收图片流的参数名
}
List<MultipartBody.Part> parts=builder.build().parts();
Observable observable=ServiceFactory.getInstance().createService(ApiService.class).uploadMemberIcon(parts);
observable.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new HttpResultSubscriber<UploadImgResult>() {
@Override
public void onSuccess(UploadImgResult uploadImgResult) {
int error_code=uploadImgResult.error_code;
String msg=uploadImgResult.msg;
String path=uploadImgResult.imgPath;
Log.i("zcb","code:"+error_code+"msg:"+msg+"path:"+path);
registerView.onUploadAvatarImgResult(msg,error_code,path);
}
@Override
public void _onError(Throwable e) {
}
});
}
最后是后台服务器端测试文件上传用的servlet代码UploadImg.java,
服务端环境tomcat8.5 jdk1.8
package wzly; import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.util.Iterator;
import java.util.List; import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import org.apache.commons.fileupload.DiskFileUpload;
import org.apache.commons.fileupload.FileItem;
import org.json.JSONException;
import org.json.JSONObject; /**
* Servlet implementation class UploadImg
*/
@WebServlet("/UploadImg")
public class UploadImg extends HttpServlet {
private static final long serialVersionUID = 1L; public UploadImg() {
}
private String fileName="";
private boolean success=false;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
response.getWriter().append("you are using get method Served at: ").append(request.getContextPath());
} //服务器servlet代码
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException { System.out.println("开始接受文件");
String temp=request.getSession().getServletContext().getRealPath("/")+"temp"; //临时目录
System.out.println("temp="+temp);
String loadpath=request.getSession().getServletContext().getRealPath("/")+"Image"; //上传文件存放目录
System.out.println("loadpath="+loadpath);
DiskFileUpload fu =new DiskFileUpload();
fu.setSizeMax(5*1024*1024); // 设置允许用户上传文件大小,单位:字节
fu.setSizeThreshold(4096); // 设置最多只允许在内存中存储的数据,单位:字节
fu.setRepositoryPath(temp); // 设置一旦文件大小超过getSizeThreshold()的值时数据存放在硬盘的目录 //开始读取上传信息
int index=0;
List fileItems =null;
try {
fileItems = fu.parseRequest(request);
System.out.println("fileItems="+fileItems);
} catch (Exception e) {
e.printStackTrace();
}
Iterator iter = fileItems.iterator(); // 依次处理每个上传的文件
while (iter.hasNext())
{
FileItem item = (FileItem)iter.next();// 忽略其他不是文件域的所有表单信息
if (!item.isFormField())
{
fileName = item.getName();//获取上传文件名,包括路径
fileName=fileName.substring(fileName.lastIndexOf("\\")+1);//从全路径中提取文件名
long size = item.getSize();
if((fileName==null||fileName.equals("")) && size==0)
continue;
int point = fileName.indexOf(".");
fileName=(new Date()).getTime()+fileName.substring(point,fileName.length());
index++;
File fNew=new File(loadpath, fileName);
try {
item.write(fNew);
success=true;
} catch (Exception e) {
// TODO Auto-generated catch block
success=false;
e.printStackTrace();
}
}
else//取出不是文件域的所有表单信息
{ String fieldName=item.getFieldName();
String fieldvalue = item.getString();
//如果包含中文应写为:(转为UTF-8编码)
System.out.println(fieldName);
System.out.println(fieldvalue);
// String fieldvalue = new String(item.getString().getBytes(),"UTF-8");
}
} JSONObject json=new JSONObject();
try {
if(success){
String imgPath="image/"+fileName.substring(0, fileName.length()); json.put("error_code", 1);
json.put("msg", "upload success");
json.put("imgPath", imgPath); }else{
json.put("error_code", 0);
json.put("msg", "upload fail");
json.put("imgPath", "");
}
} catch (JSONException e) {
e.printStackTrace();
} response.getWriter().append(json.toString());
// response.sendRedirect("result.jsp?imgPath="+ json.toString());
} }
Rxjava+Retrofit2+Okhttp3多文件上传(服务器端代码+客户端代码)的更多相关文章
- MVC文件上传09-使用客户端jQuery-File-Upload插件和服务端Backload组件让每个用户有专属文件夹,并在其中创建分类子文件夹
为用户创建专属上传文件夹后,如果想在其中再创建分类子文件夹,该怎么做?可以在提交文件的视图中再添加一个隐藏域,并设置 name="uploadContext". 相关兄弟篇: MV ...
- MVC文件上传08-使用客户端jQuery-File-Upload插件和服务端Backload组件让每个用户有专属文件夹
当需要为每个用户建立一个专属上传文件夹的时候,可以在提交文件的视图中添加一个隐藏域,并设置name="objectContext". 相关兄弟篇: MVC文件上传01-使用jque ...
- MVC文件上传07-使用客户端jQuery-File-Upload插件和服务端Backload组件裁剪上传图片
本篇通过在配置文件中设置,对上传图片修剪后保存到指定文件夹. 相关兄弟篇: MVC文件上传01-使用jquery异步上传并客户端验证类型和大小 MVC文件上传02-使用HttpPostedFileB ...
- MVC文件上传06-使用客户端jQuery-File-Upload插件和服务端Backload组件自定义控制器上传多个文件
当需要在控制器中处理除了文件的其他表单字段,执行控制器独有的业务逻辑......等等,这时候我们可以自定义控制器. MVC文件上传相关兄弟篇: MVC文件上传01-使用jquery异步上传并客户端验证 ...
- MVC文件上传05-使用客户端jQuery-File-Upload插件和服务端Backload组件自定义上传文件夹
在零配置情况下,文件的上传文件夹是根目录下的Files文件夹,如何自定义文件的上传文件夹呢? MVC文件上传相关兄弟篇: MVC文件上传01-使用jquery异步上传并客户端验证类型和大小 MVC文 ...
- NetworkComms 文件上传下载和客户端自动升级(非开源)
演示程序下载地址:http://pan.baidu.com/s/1geVfmcr 淘宝地址:https://shop183793329.taobao.com 联系QQ号:3201175853 许可:购 ...
- MVC文件上传04-使用客户端jQuery-File-Upload插件和服务端Backload组件实现多文件异步上传
本篇使用客户端jQuery-File-Upload插件和服务端Badkload组件实现多文件异步上传.MVC文件上传相关兄弟篇: MVC文件上传01-使用jquery异步上传并客户端验证类型和大小 ...
- Java 将要上传的文件上传至指定路径代码实现
代码: /** * 上传文件到指定路径 * @param mFile 要上传的文件 * @param path 指定路径 */ public static void uploadFile(Multip ...
- C#使用HTML文件中的file文件上传,用C#代码接收上传文件
单独做图片上传很简单,如果要客户端要上传头像保存到服务器就要稍微麻烦一点点了. 不多说了,直接上源码: private void Upload() { string jsonInfo = string ...
随机推荐
- [转载]Python兵器谱
转载自:http://www.52nlp.cn/python-网页爬虫-文本处理-科学计算-机器学习-数据挖掘 曾经因为NLTK的缘故开始学习Python,之后渐渐成为我工作中的第一辅助脚本语言,虽然 ...
- OpenRisc-43-or1200的IF模块分析
引言 “喂饱饥饿的CPU”,是计算机体系结构设计者时刻要考虑的问题.要解决这个问题,方法大体可分为两部分,第一就是利用principle of locality而引进的cache技术,缩短取指时间,第 ...
- Appium移动自动化测试(一)--安装Appium(转)
Appium移动自动化测试(一)--安装Appium 2015-05-30 17:48 by 虫师, 70668 阅读, 13 评论, 收藏, 编辑 Appium 自动化测试是很早之前就想学习和研究的 ...
- Mysql Binlog日志详解
一.Mysql Binlog格式介绍 Mysql binlog日志有三种格式,分别为Statement,MiXED,以及ROW! 1.Statement:每一条会修改数据的sql都会记录在 ...
- BASH_SOURCE 用法
参考 bash少见的用法 http://blog.csdn.net/wonderisland/article/details/22892759. 原有项目里自带的启动脚本用到了bash_source获 ...
- Android Developers:两个视图渐变
淡入淡出动画(也被称为渐隐)逐渐淡出一个UI组件,同时淡入另一个.这个动画在你想在你的应用程序中切换内容或者是视图的情况下非常有用.淡入淡出非常微妙并短,但支持从一个屏幕到下一个屏幕流畅的过渡.当你不 ...
- motan源码分析九:开关
在前面的文章中,我们已经发现了开关的踪影,例如cluster,motan支持多个cluster,当前的cluster因为开关关闭的情况下,就会使用下一个cluster. 1.开关相关的类和接口主要都在 ...
- Android中监听ScrollView滑动停止和滑动到底部
1.监听ScrollView滑动停止: /********************监听ScrollView滑动停止*****************************/ scrollView.s ...
- 在Quick-cocos2dx中使用云风pbc解析Protocol Buffers,支持win、mac、ios、android
本例主要介绍 如何将 pbc 集成到quick-cocos2dx框架中,让我们的cocos2dx客户端Lua拥有编解码Protocol Buffers能力. 参考: 云风pbc的用法: http:// ...
- java——递归调用
递归函数调用调用本身,并通过自己的相应参数,这个计算过程中进行层,直到满足某些条件,只要停止呼叫. 递归函数的特点 1.函数要直接或间接调用自身. 2.要有递归终止条件检查.即递归终止的条件被满足后. ...