Retofit+Okhttp表单上传文件及参数处理大全

39 篇文章 1 订阅
15 篇文章 0 订阅

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 + "original.png"));
Map<String, RequestBody> map = new HashMap<>();
//这里的key必须这么写,否则服务端无法识别
map.put("file\"; filename=\""+ file.getName(), fileRQ);
map.put("file\"; filename=\""+ "2.png", 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 + "original.png"));
MultipartBody.Part two=MultipartBody.Part.createFormData("one","one.png",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 okhttp3.Interceptor
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import java.util.concurrent.TimeUnit

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 = Application.context
        val instance = SingletonHolder.helper

    }

    init {
        headerInterceptor = Interceptor {
            val request = it.request().newBuilder()
                .addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8")
                .addHeader("Connection", "keep-alive")
                .addHeader("timestamp", (System.currentTimeMillis() / 1000).toString())  
                .build()

            it.proceed(request)
        }
        SslUtils.initSslSocketFactorySingleByAll(context.applicationContext)
        logInterceptor = HttpLoggingInterceptor()
        logInterceptor.level = HttpLoggingInterceptor.Level.BODY

        okHttpClient = OkHttpClient.Builder()
            .connectTimeout(DEFAULT_CONNECT_TIME.toLong(), TimeUnit.SECONDS) //连接超时时间
            .writeTimeout(DEFAULT_WRITE_TIME.toLong(), TimeUnit.SECONDS) //设置写操作超时时间
            .readTimeout(DEFAULT_READ_TIME.toLong(), TimeUnit.SECONDS) //设置读操作超时时间
            .addInterceptor(headerInterceptor)
            .addInterceptor(LoggingInterceptor())
            .sslSocketFactory(SslUtils.sSLSocketFactory,SslUtils.trustManager)
            .build()
        retrofit = Retrofit.Builder()
            .client(okHttpClient) //设置使用okHttp网络请求
            .baseUrl(BASE_URL) //设置服务器路径
            .addConverterFactory(GsonConverterFactory.create()) //添加转化库,默认是Gson
            .build()
    }



    fun <T> create(service: Class<T>?): T {
        return retrofit.create(service)
    }
}
日志拦截
import java.io.IOException;
import java.nio.charset.Charset;

import okhttp3.Headers;
import okhttp3.Interceptor;
import okhttp3.MultipartBody;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okio.Buffer;
import okio.BufferedSource;

public class LoggingInterceptor implements Interceptor {
    private static final String TAG = "LoggingInterceptor";

    @Override
    public Response intercept(Chain chain) throws IOException {
        Request original = chain.request();
        Response response = chain.proceed(original);
        LogUtil.e(TAG, String.format("...\n请求链接:%s\n请求方式:%s\n请求头:\n%s\n请求参数:\n%s\n响应码:%s\n请求响应:\n%s", original.url(),
                original.method(), getRequestHeaders(original), getRequestInfo(original), response.code(), getResponseInfo(response)));
        return response;
    }

    /**
     * 打印请求头
     *
     * @param request 请求的对象
     */
    private String getRequestHeaders(Request request) {
        String str = "";
        if (request == null) {
            return str;
        }
        Headers headers = request.headers();
        if (headers == null) {
            return str;
        }
        return headers.toString();
    }

    /**
     * 打印请求消息
     *
     * @param request 请求的对象
     */
    private String getRequestInfo(Request request) {
        String str = "";
        if (request == null) {
            return str;
        }
        RequestBody requestBody = request.body();
        if (requestBody == null) {
            return str;
        }
        if (requestBody instanceof MultipartBody) {
            return "MultipartBody不显示";
        }
        try {
            Buffer bufferedSink = new Buffer();
            requestBody.writeTo(bufferedSink);
            Charset charset = Charset.forName("utf-8");
            str = bufferedSink.readString(charset);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return str;
    }

    /**
     * 打印返回消息
     *
     * @param response 返回的对象
     */
    private String getResponseInfo(Response response) {
        String str = "";
        if (response == null || !response.isSuccessful()) {
            return str;
        }
        ResponseBody responseBody = response.body();
        long contentLength = responseBody.contentLength();
        BufferedSource source = responseBody.source();
        try {
            source.request(Long.MAX_VALUE); // Buffer the entire body.
        } catch (Exception e) {
            e.printStackTrace();
        }
        Buffer buffer = source.buffer();
        Charset charset = Charset.forName("utf-8");
        if (contentLength != 0) {
            str = buffer.clone().readString(charset);
        }
        return str;
    }
}
发送+接收数据拦截
import android.content.Context;
import android.text.TextUtils;

import com.google.gson.Gson;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.nio.charset.UnsupportedCharsetException;
import java.util.HashMap;
import java.util.Set;

import okhttp3.FormBody;
import okhttp3.Headers;
import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okio.Buffer;
import okio.BufferedSource;

/**
 * 处理拦截
 */
public class SafeInterceptor implements Interceptor {
    private String TAG = "SafeInterceptor";

    @Override
    public Response intercept(Chain chain) throws IOException {

        Request request = chain.request();
        //指定域名不拦截
        if (request.url().toString().endsWith("XXXX")) {
            return chain.proceed(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);
        Request.Builder newBuilder = request.newBuilder();
        newBuilder.addHeader("X-Unique-Sign", sign);
        //6.body数据加密
        RequestBody requestBody = request.body();
        if (requestBody != null) {
            if (requestBody instanceof FormBody) {
                newBuilder.post(requestBody);
            } else if (requestBody instanceof MultipartBody) {
                newBuilder.post(requestBody);
            } else {
                String postBodyString = bodyToString(requestBody);
                LogUtil.e(TAG, "请求参数:" + postBodyString);
                if (!TextUtils.isEmpty(postBodyString)) {
                    String type = request.method();
                    if ("Post".equalsIgnoreCase(type)){
                        newBuilder.post(RequestBody.create(MediaType.parse("text/plain;charset=UTF-8"), allBase));
                    }else if ("Put".equalsIgnoreCase(type)){
                        newBuilder.put(RequestBody.create(MediaType.parse("text/plain;charset=UTF-8"), allBase));
                    }
                }
            }
        }
        //7.返回数据
        request = newBuilder.build();
        Response response = chain.proceed(request);
        return getResponseString(response, sign, app_secret);
    }

    private void getBody(Request request, HashMap<String, String> needSignMap) {
        RequestBody requestBody = request.body();
        if (requestBody == null) return;
        MediaType type = requestBody.contentType();
        if (type != null) {
            LogUtil.e(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)) {
                        needSignMap.put(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 (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("=");
                            try {
                                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);
                                }
                            } catch (IOException e) {
                                LogUtil.e(TAG,"getBody multipart:"+e.getMessage());
                            }
                        } 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);
                        }
                    }
                }
                LogUtil.e(TAG,"文本参数:"+params);
                params.remove("file");
                LogUtil.e(TAG,"文件参数:"+files);
                needSignMap.putAll(params);
            } else {
                if (type.toString().contains("x-www-form-urlencoded")) {
                    HashMap<String, String> urlencodedMap = new HashMap<>();
                    //buffer流
                    Buffer buffer = new Buffer();
                    try {
                        requestBody.writeTo(buffer);
                        String oldParamsJson = buffer.readUtf8();
                        Gson gson = new Gson();
                        urlencodedMap = gson.fromJson(oldParamsJson, HashMap.class);  //原始参数
                        needSignMap.putAll(urlencodedMap);
                    } catch (IOException e) {
                        LogUtil.e(TAG,"getBody form:"+e.getMessage());
                    }
                }
            }
        }


    }

    private void getQuery(Request request, HashMap<String, String> needSignMap) {
        Set<String> paramterSet = request.url().queryParameterNames();
        for (String itmeName : paramterSet) {
            String itemValue = request.url().queryParameter(itmeName);
            needSignMap.put(itmeName, itemValue);
        }
    }

    private void getRequestHeaders(Request request, HashMap<String, String> signMap) {
        if (request != null) {
            Headers headers = request.headers();
            if (headers != null) {
                String timestampValue = headers.get("timestamp");
                if (!TextUtils.isEmpty(timestampValue)) {
                    signMap.put("timestamp", timestampValue);
                }
            }
        }
    }

    private String bodyToString(final RequestBody request) {
        try {
            final RequestBody copy = request;
            final Buffer buffer = new Buffer();
            if (copy != null){
                copy.writeTo(buffer);
            } else {
                return "";
            }
            return buffer.readUtf8();
        } catch (final IOException e) {
            LogUtil.e(TAG, "bodyToString IOException");
            return "";
        }
    }


    /*处理响应*/
    private Response getResponseString(Response response, String sign, String app_secret) throws UnsupportedEncodingException {
        ResponseBody responseBody = response.body();
        if (responseBody != null) {
            long contentLength = responseBody.contentLength();
            //判断返回内容中data加密
            if (bodyEncoded(response.headers())) {
                BufferedSource source = responseBody.source();
                try {
                    source.request(Long.MAX_VALUE); // Buffer the entire body.
                } catch (IOException e) {
                    LogUtil.e(TAG, "getResponseString IOException:"+ e.getMessage());
                }
                Buffer buffer = source.buffer();

                Charset charset = Charset.forName("UTF-8");
                MediaType contentType = responseBody.contentType();
                if (contentType != null) {
                    try {
                        charset = contentType.charset(Charset.forName("UTF-8"));
                    } catch (UnsupportedCharsetException e) {
                        LogUtil.e(TAG, e.getMessage());
                    }
                }

                if (contentLength != 0) {
                    String res = buffer.clone().readString(charset);

//                    LogUtil.e(TAG, "响应数据:" + res);
                    BaseAResponse baseAsResponse = new Gson().fromJson(res, BaseAResponse.class);
                    String secretData = baseAesResponse.getData();
                    String result = secretData;
                    if (!TextUtils.isEmpty(secretData)) {
                        String contentEncoding = response.headers().get("Algorithm");
               
                      /*  if (!TextUtils.isEmpty(result)){
                            BaseResponse response = new Gson().fromJson(result, BaseEcdhResponse.class);
                        }*/
                    } else {
                        result = res;
                    }
                    LogUtil.e(TAG, "解密数据:" + result);

                    MediaType mediaType = responseBody.contentType();
                    return response.newBuilder().body(ResponseBody.create(
                            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);
        }


————————————————

                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
                        
原文链接:https://blog.csdn.net/fepengwang/article/details/131110380

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值