Retofit+Okhttp表单上传文件及参数处理大全
一、Retofit配置上传文件的方式
1. 仅参数上传
方式一
@FormUrlEncoded
@POST("upload")
Call<ResponseBody> uploadParams(@Field("username")String username,@Field("token")String token);
方式二
@FormUrlEncoded
@POST("upload")
Call<ResponseBody> uploadParams(@FieldMap Map<String,String> map);
方式三
@POST("upload")
Call<ResponseBody> uploadParams(@Body RequestBody body);
2. 文件上传
单文件上传
@Multipart
@POST("upload")
Call<ResponseBody> uploadOneFile(@Part MultipartBody.Part body);
调用方式:
File file = new File("");
RequestBody fileRQ = RequestBody.create(MediaType.parse("image/*"), file);
MultipartBody.Part part MultipartBody.Part.createFormData("picture", file.getName(), fileRQ);
Call<ResponseBody> uploadCall = downloadService.uploadOneFile(part);
多文件上传
方式一
@Multipart
@POST("upload")
Call<ResponseBody> uploadFiles(@PartMap Map<String, RequestBody> map);
调用:
RequestBody fb = RequestBody.create(MediaType.parse("text/plain"), "hello,retrofit");
RequestBody fileTwo = RequestBody.create(MediaType.parse("image/*"), new File(Environment.getExternalStorageDirectory()
+ file.separator + ""));
Map<String, RequestBody> map = new HashMap<>();
//这里的key必须这么写,否则服务端无法识别
map.put("file\"; filename=\""+ file.getName(), fileRQ);
map.put("file\"; filename=\""+ "", fileTwo);
Call<ResponseBody> uploadCall = downloadService.uploadFiles(map);
方式二
@Multipart
@POST("upload")
Call<ResponseBody> uploadFiles(@Part List<MultipartBody.Part> parts);
调用:
RequestBody fileRQ = RequestBody.create(MediaType.parse("image/*"), file);
MultipartBody.Part part = MultipartBody.Part.createFormData("picture", file.getName(), fileRQ);
RequestBody fb = RequestBody.create(MediaType.parse("text/plain"), "hello,retrofit");
RequestBody fileTwo = RequestBody.create(MediaType.parse("image/*"), new File(Environment.getExternalStorageDirectory()
+ file.separator + ""));
MultipartBody.Part two=MultipartBody.Part.createFormData("one","",fileTwo);
List<MultipartBody.Part> parts=new ArrayList<>();
parts.add(part);
parts.add(two);
Call<ResponseBody> uploadCall = downloadService.uploadFiles(parts);
3. 文件+参数混合上传
方式一
@Multipart
@POST("upload")
Call<ResponseBody> uploadFile(@Part("body") RequestBody body, @Part MultipartBody.Part file);
调用:
MultipartBody.Part part = MultipartBody.Part.createFormData("picture", file.getName(), fileRQ);
RequestBody fb =RequestBody.create(MediaType.parse("text/plain"), "hello,retrofit");
Call<ResponseBody> uploadCall = downloadService.uploadFile(fb,part);
方式二
@POST("upload")
Call<ResponseBody> uploadFile(@Body RequestBody body);
调用:
File file = new File("path");
RequestBody fileRQ = RequestBody.create(MediaType.parse("multipart/form-data"), file);
MultipartBody.Part part = MultipartBody.Part.createFormData("picture", file.getName(), fileRQ);
RequestBody body=new MultipartBody.Builder()
.addFormDataPart("userName","lange")
.addFormDataPart("token","dxjdkdjkj9203kdckje0")
.addFormDataPart("header",file.getName(),fileRQ)
.build();
Call<ResponseBody> uploadCall = downloadService.uploadFile(body);
uploadCall.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
Log.i("upload", response.isSuccessful() + "");
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
}
});
二、Okhttp拦截器添加
Retrofit配置
import
import
import
import
import
import
class RetrofitHelper private constructor() {
private var okHttpClient: OkHttpClient
private var retrofit: Retrofit
private val headerInterceptor: Interceptor
private val logInterceptor: HttpLoggingInterceptor
private object SingletonHolder {
val helper = RetrofitHelper()
}
companion object {
private var BASE_URL = ""
private const val DEFAULT_CONNECT_TIME = 10
private const val DEFAULT_WRITE_TIME = 15
private const val DEFAULT_READ_TIME = 15
const val TOKEN_KEY = "token"
const val UID_KEY = "uid"
const val LANGUAGE_KEY = "language"
const val COUNTRY_KEY = "country"
const val SUCCESS_CODE = 1
val context =
val instance =
}
init {
headerInterceptor = Interceptor {
val request = ().newBuilder()
.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8")
.addHeader("Connection", "keep-alive")
.addHeader("timestamp", (() / 1000).toString())
.build()
(request)
}
()
logInterceptor = HttpLoggingInterceptor()
=
okHttpClient = ()
.connectTimeout(DEFAULT_CONNECT_TIME.toLong(), ) //连接超时时间
.writeTimeout(DEFAULT_WRITE_TIME.toLong(), ) //设置写操作超时时间
.readTimeout(DEFAULT_READ_TIME.toLong(), ) //设置读操作超时时间
.addInterceptor(headerInterceptor)
.addInterceptor(LoggingInterceptor())
.sslSocketFactory(,)
.build()
retrofit = ()
.client(okHttpClient) //设置使用okHttp网络请求
.baseUrl(BASE_URL) //设置服务器路径
.addConverterFactory(()) //添加转化库,默认是Gson
.build()
}
fun <T> create(service: Class<T>?): T {
return (service)
}
}
日志拦截
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
public class LoggingInterceptor implements Interceptor {
private static final String TAG = "LoggingInterceptor";
@Override
public Response intercept(Chain chain) throws IOException {
Request original = ();
Response response = (original);
(TAG, ("...\n请求链接:%s\n请求方式:%s\n请求头:\n%s\n请求参数:\n%s\n响应码:%s\n请求响应:\n%s", (),
(), getRequestHeaders(original), getRequestInfo(original), (), getResponseInfo(response)));
return response;
}
/**
* 打印请求头
*
* @param request 请求的对象
*/
private String getRequestHeaders(Request request) {
String str = "";
if (request == null) {
return str;
}
Headers headers = ();
if (headers == null) {
return str;
}
return ();
}
/**
* 打印请求消息
*
* @param request 请求的对象
*/
private String getRequestInfo(Request request) {
String str = "";
if (request == null) {
return str;
}
RequestBody requestBody = ();
if (requestBody == null) {
return str;
}
if (requestBody instanceof MultipartBody) {
return "MultipartBody不显示";
}
try {
Buffer bufferedSink = new Buffer();
(bufferedSink);
Charset charset = ("utf-8");
str = (charset);
} catch (Exception e) {
();
}
return str;
}
/**
* 打印返回消息
*
* @param response 返回的对象
*/
private String getResponseInfo(Response response) {
String str = "";
if (response == null || !()) {
return str;
}
ResponseBody responseBody = ();
long contentLength = ();
BufferedSource source = ();
try {
(Long.MAX_VALUE); // Buffer the entire body.
} catch (Exception e) {
();
}
Buffer buffer = ();
Charset charset = ("utf-8");
if (contentLength != 0) {
str = ().readString(charset);
}
return str;
}
}
发送+接收数据拦截
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
import ;
/**
* 处理拦截
*/
public class SafeInterceptor implements Interceptor {
private String TAG = "SafeInterceptor";
@Override
public Response intercept(Chain chain) throws IOException {
Request request = ();
//指定域名不拦截
if (().toString().endsWith("XXXX")) {
return (request);
}
HashMap<String, String> needSignMap = new HashMap<>();
//1.获取head数据
getRequestHeaders(request, needSignMap);
//2.获取queryMap数据
getQuery(request, needSignMap);
//3.获取mediaType:x-www-form-urlencoded,Body数据
//4.获取mediaType:multipart/form-data,value 类型和 file 类型。
getBody(request, needSignMap);
newBuilder = ();
("X-Unique-Sign", sign);
//数据加密
RequestBody requestBody = ();
if (requestBody != null) {
if (requestBody instanceof FormBody) {
(requestBody);
} else if (requestBody instanceof MultipartBody) {
(requestBody);
} else {
String postBodyString = bodyToString(requestBody);
(TAG, "请求参数:" + postBodyString);
if (!(postBodyString)) {
String type = ();
if ("Post".equalsIgnoreCase(type)){
((("text/plain;charset=UTF-8"), allBase));
}else if ("Put".equalsIgnoreCase(type)){
((("text/plain;charset=UTF-8"), allBase));
}
}
}
}
//7.返回数据
request = ();
Response response = (request);
return getResponseString(response, sign, app_secret);
}
private void getBody(Request request, HashMap<String, String> needSignMap) {
RequestBody requestBody = ();
if (requestBody == null) return;
MediaType type = ();
if (type != null) {
(TAG, "接口请求Type:" + type);
if (requestBody instanceof FormBody) {
for (int i = 0; i < ((FormBody) requestBody).size(); i++) {
String name = ((FormBody) requestBody).encodedName(i);
if (!"file".equalsIgnoreCase(name)) {
(name, ((FormBody) requestBody).encodedValue(i));
}
}
} else if (requestBody instanceof MultipartBody) {
MultipartBody body = (MultipartBody) requestBody;
HashMap<String, String> params = new HashMap<>();
HashMap<String, String> files = new HashMap<>();
for ( part : ()) {
RequestBody body1 = ();
Headers headers = ();
if (headers != null && () > 0) {
String[] split = (0).replace(" ", "").replace("\"", "").split(";");
if ( == 2) {
//文本
String[] keys = split[1].split("=");
try {
if ( > 1 && () < 1024) {
String key = keys[1];
String value = "";
Buffer buffer = new Buffer();
(buffer);
value = buffer.readUtf8();
(key, value);
}
} catch (IOException e) {
(TAG,"getBody multipart:"+());
}
} else if ( == 3) {
//文件
String fileKey = "";
String fileName = "";
String[] keys = split[1].split("=");
String[] names = split[2].split("=");
if ( > 1) fileKey = keys[1];
if ( > 1) fileName = names[1];
(fileKey, fileName);
}
}
}
(TAG,"文本参数:"+params);
("file");
(TAG,"文件参数:"+files);
(params);
} else {
if (().contains("x-www-form-urlencoded")) {
HashMap<String, String> urlencodedMap = new HashMap<>();
//buffer流
Buffer buffer = new Buffer();
try {
(buffer);
String oldParamsJson = buffer.readUtf8();
Gson gson = new Gson();
urlencodedMap = (oldParamsJson, ); //原始参数
(urlencodedMap);
} catch (IOException e) {
(TAG,"getBody form:"+());
}
}
}
}
}
private void getQuery(Request request, HashMap<String, String> needSignMap) {
Set<String> paramterSet = ().queryParameterNames();
for (String itmeName : paramterSet) {
String itemValue = ().queryParameter(itmeName);
(itmeName, itemValue);
}
}
private void getRequestHeaders(Request request, HashMap<String, String> signMap) {
if (request != null) {
Headers headers = ();
if (headers != null) {
String timestampValue = ("timestamp");
if (!(timestampValue)) {
("timestamp", timestampValue);
}
}
}
}
private String bodyToString(final RequestBody request) {
try {
final RequestBody copy = request;
final Buffer buffer = new Buffer();
if (copy != null){
(buffer);
} else {
return "";
}
return buffer.readUtf8();
} catch (final IOException e) {
(TAG, "bodyToString IOException");
return "";
}
}
/*处理响应*/
private Response getResponseString(Response response, String sign, String app_secret) throws UnsupportedEncodingException {
ResponseBody responseBody = ();
if (responseBody != null) {
long contentLength = ();
//判断返回内容中data加密
if (bodyEncoded(())) {
BufferedSource source = ();
try {
(Long.MAX_VALUE); // Buffer the entire body.
} catch (IOException e) {
(TAG, "getResponseString IOException:"+ ());
}
Buffer buffer = ();
Charset charset = ("UTF-8");
MediaType contentType = ();
if (contentType != null) {
try {
charset = (("UTF-8"));
} catch (UnsupportedCharsetException e) {
(TAG, ());
}
}
if (contentLength != 0) {
String res = ().readString(charset);
// (TAG, "响应数据:" + res);
BaseAResponse baseAsResponse = new Gson().fromJson(res, );
String secretData = ();
String result = secretData;
if (!(secretData)) {
String contentEncoding = ().get("Algorithm");
/* if (!(result)){
BaseResponse response = new Gson().fromJson(result, );
}*/
} else {
result = res;
}
(TAG, "解密数据:" + result);
MediaType mediaType = ();
return ().body((
mediaType,
result
)).build();
}
}
}
return response;
}
}
三、MultipartBody内部数据解析
直接上代码示例
kotlin
if (requestBody is MultipartBody) {
val params = mutableMapOf<String, String>()
val files = mutableMapOf<String, String>()
requestBody.parts().forEach {
val body = it.body()
it.headers()?.let {
val header = it.value(0)
val split = header.replace(" ", "").replace("\"", "").split(";")
when (split.size) {
2 -> {
//文本参数
val keys = split[1].split("=")
if (keys.size > 1 && body.contentLength() < 1024) {
val key = keys[1]
val buffer = Buffer()
body.writeTo(buffer)
val value = buffer.readUtf8()
params[key] = value
}
}
3 -> {
//文件
val fileKeys = split[1].split("=")
val fileKey = if (fileKeys.size > 1) {
fileKeys[1]
} else ""
val nameValue = split[2].split("=")
val fileName = if (nameValue.size > 1) nameValue[1] else ""
files[fileKey] = fileName
}
}
}
}
println("文件-->$files")
println("文本-->$params")
}
java
if (requestBody instanceof MultipartBody) {
MultipartBody body = (MultipartBody) requestBody;
Map<String, String> params = new HashMap<>();
Map<String, String> files = new HashMap<>();
for (MultipartBody.Part part : body.parts()) {
RequestBody body1 = part.body();
Headers headers = part.headers();
if (headers != null && headers.size() > 0) {
String[] split = headers.value(0).replace(" ", "").replace("\"", "").split(";");
if (split.length == 2) {
//文本
String[] keys = split[1].split("=");
if (keys.length > 1 && body1.contentLength() < 1024) {
String key = keys[1];
String value = "";
Buffer buffer = new Buffer();
body1.writeTo(buffer);
value = buffer.readUtf8();
params.put(key, value);
}
} else if (split.length == 3) {
//文件
String fileKey = "";
String fileName = "";
String[] keys = split[1].split("=");
String[] names = split[2].split("=");
if (keys.length > 1) fileKey = keys[1];
if (names.length > 1) fileName = names[1];
files.put(fileKey, fileName);
}
}
}
System.out.println("文本参数-->" + params);
System.out.println("文件参数-->" + files);
}