https+retrofit实现多文件上传

okhttp、retrofit初始化

自定义安全套接字socket

public class Tls12SocketFactory extends SSLSocketFactory {

    private static final String[] TLS_SUPPORT_VERSION = {"TLSv1.1", "TLSv1.2"};

    final SSLSocketFactory delegate;

    public Tls12SocketFactory(SSLSocketFactory base) {
        this.delegate = base;
    }

    @Override
    public String[] getDefaultCipherSuites() {
        return delegate.getDefaultCipherSuites();
    }

    @Override
    public String[] getSupportedCipherSuites() {
        return delegate.getSupportedCipherSuites();
    }

    @Override
    public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
        return patch(delegate.createSocket(s, host, port, autoClose));
    }

    @Override
    public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
        return patch(delegate.createSocket(host, port));
    }

    @Override
    public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException {
        return patch(delegate.createSocket(host, port, localHost, localPort));
    }

    @Override
    public Socket createSocket(InetAddress host, int port) throws IOException {
        return patch(delegate.createSocket(host, port));
    }

    @Override
    public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
        return patch(delegate.createSocket(address, port, localAddress, localPort));
    }

    private Socket patch(Socket s) {
        if (s instanceof SSLSocket) {
            ((SSLSocket) s).setEnabledProtocols(TLS_SUPPORT_VERSION);
        }
        return s;
    }

}

用SSLSocketFactory初始化OKHttp

private Map<Integer, RequestIsSuccess> requestInterfMap = new TreeMap<>();
private APIManager.APIInterface apiInterface;
private Retrofit retrofit;
private OkHttpClient okHttpClient;
public X509TrustManager createX509TrustManager() {
        return new X509TrustManager() {
            @Override
            public void checkClientTrusted(X509Certificate[] chain, String authType) {

            }

            @Override
            public void checkServerTrusted(X509Certificate[] chain, String authType) {

            }

            @Override
            public X509Certificate[] getAcceptedIssuers() {
                return new java.security.cert.X509Certificate[]{};
            }
        };
    }
    
public SSLSocketFactory createTLSSocketFactory(X509TrustManager x509TrustManager) {
        SSLSocketFactory ssfFactory = null;
        try {
            SSLContext sc = SSLContext.getInstance("TLS");
            sc.init(null, new TrustManager[]{x509TrustManager}, new SecureRandom());
            ssfFactory = sc.getSocketFactory();
        } catch (Exception e) {
            Log.e("APIManager", " -=-=- createSSLSocketFactory: Create SSLSocketFactory Error", e);
        }
        return ssfFactory;
    }

X509TrustManager x509 = createX509TrustManager();
public SSLSocketFactory socketFactory = new Tls12SocketFactory(createTLSSocketFactory(x509));

public HostnameVerifier createHostnameVerifier() {
        return (hostname, session) -> true;
    }
 
private CookieJar createCookieJar() {
        return new CookieJar() {
            @Override
            public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
                cookieList.addAll(cookies);
            }

            @Override
            public List<Cookie> loadForRequest(HttpUrl url) {
                try {
                    if (url.isHttps() && !BASE_URL.contains(String.valueOf(url.port()))) {
                        setIpPort(true, url.host(), String.valueOf(url.port()));
                    }

                } catch (ConcurrentModificationException e) {
                    Log.e("APIManager", " -=-=- loadForRequest: e", e);
                }

                return cookieList;
            }
        };
    }

初始化okhttp

public void init() {
        cookieList = new ArrayList<>();
        requestMap = new HashMap<>();
        okHttpClient = new OkHttpClient.Builder()
                .readTimeout(10, TimeUnit.SECONDS)
                .connectTimeout(10, TimeUnit.SECONDS)
                .sslSocketFactory(socketFactory, x509)
                .hostnameVerifier(createHostnameVerifier())
                .cookieJar(createCookieJar()).build();
    }

初始化retrofit

public APIManager setIpPort(boolean isHttps, String ip, String port) {
        IP_PORT = ip + ":" + port;
        String prefix;

        if (isHttps) prefix = "https://";
        else prefix = "http://";

        BASE_URL = prefix + IP_PORT/* + "/" + PROJECT_ROOT_NAME + "/"*/;
        Log.d("APIManager", " -=-=- setIpPort: BaseUrl:" + BASE_URL);

        retrofit = new Retrofit.Builder().baseUrl(BASE_URL).client(okHttpClient).build();
        apiInterface = retrofit.create(APIManager.APIInterface.class);
        return this;
    }

定义retrofit请求接口

一般请求使用第一个接口,多文件上传请求使用第二个接口

private interface APIInterface {

        @FormUrlEncoded
        @POST("{path}/{apiPath}")
        Call<ResponseBody> request(@Path("path") String path, @Path("apiPath") String apiPath, @FieldMap Map<String, Object> requestMap);

        @POST("{path}/{apiPath}")
        Call<ResponseBody> uploadFiles(@Path("path") String path, @Path("apiPath") String apiPath, @Body MultipartBody multipartBody);

    }

定义retrofit回调

private Call<ResponseBody> retrofitEnqueue(int hashCode, String path, String apiPath, Call<ResponseBody> responseBodyCall) {

        responseBodyCall.enqueue(new Callback<ResponseBody>() {
            @Override
            public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
//                Log.d("APIManager", " -=-=- onResponse: call:" + call);
                try {
                    if (response.code() == 200) {
                        String body = response.body().string();
                        Log.d("APIManager", " -=-=- onResponse: api:" + apiPath + "  body:" + body);
                        if (checkIsReLogin(body)) return;
                        if (!checkIsSuccess(body, hashCode)) return;
                        handler.obtainMessage(REQUEST_SUCCESS_TRUE, hashCode, 0, body).sendToTarget();
                    } else {
                        handler.obtainMessage(REQUEST_FAILED, hashCode, 0, "Response Code = " + response.code()).sendToTarget();
                    }
                } catch (Exception e) {
                    Log.e(TAG, " -=-=- onResponse: ", e);
                    handler.obtainMessage(REQUEST_FAILED, hashCode, 0, "APIManager Error -> " + e.getMessage()).sendToTarget();
                } finally {
                    requestMap.clear();
                }
            }

            @Override
            public void onFailure(Call<ResponseBody> call, Throwable t) {
                Log.e(TAG, " -=-=- onFailure: ", t);
                handler.obtainMessage(REQUEST_FAILED, hashCode, 0, t.getMessage()).sendToTarget();
                requestMap.clear();
            }
        });
        return responseBodyCall;
    }

检查返回的数据

// 检查是否需要重新登录
private boolean checkIsReLogin(String body) {
        if (body.equals("logout")) {
            handler.obtainMessage(REQUEST_RELOGIN).sendToTarget();
            return true;
        } else {
            return false;
        }
    }

    // 检查服务器是否成功返回数据
    private boolean checkIsSuccess(String body, int hashCode) {
        SuccessFailedEntity loginEntity = new Gson().fromJson(body, SuccessFailedEntity.class);
        if (loginEntity.getLoginReturnWarnMsg() != null) {
            if (loginEntity.getLoginReturnWarnMsg().equals("success")) {
                return true;
            } else if (loginEntity.getLoginReturnWarnMsg().equals("NoPermission")) {
                handler.obtainMessage(REQUEST_SUCCESS_FALSE, "没有权限").sendToTarget();
                return false;
            }
        }
        JsonObject jsonObject = new JsonParser().parse(body).getAsJsonObject();

        JsonElement successStr = jsonObject.get("success");
        if (successStr == null) successStr = jsonObject.get("Success");
        if (successStr == null) {
            if (loginEntity.getLoginReturnWarnMsg().equals("UserNameOrPwdError")) {
                handler.obtainMessage(REQUEST_FAILED, hashCode, 0, "用户名或密码错误").sendToTarget();
            } else {
                handler.obtainMessage(REQUEST_FAILED, hashCode, 0, loginEntity.getLoginReturnWarnMsg()).sendToTarget();
            }
            return false;
        }

        if (successStr != null) {
            if (successStr.toString().equals("\"false\"") || successStr.toString().equals("false")) {
                SuccessFailedEntity successEntity = new Gson().fromJson(body, SuccessFailedEntity.class);
                Log.e(TAG, " -=-=- checkIsSuccess: 数据请求失败:" + successEntity);
                String msg = successEntity.getReturnMsg() == null ? successEntity.getMsg() : successEntity.getReturnMsg();
                if (msg != null && !msg.isEmpty()) {
                    handler.obtainMessage(REQUEST_SUCCESS_FALSE, hashCode, 0, msg).sendToTarget();
                } else {
                    handler.obtainMessage(REQUEST_SUCCESS_FALSE, hashCode, 0, "没有错误信息").sendToTarget();
                }
                return false;
            }
            return true;
        } else {
            handler.obtainMessage(REQUEST_SUCCESS_FALSE, hashCode, 0, "返回数据没有 Success 标识").sendToTarget();
        }
        return false;
    }

handler+回传接口返回retrofit请求结果

定义RequestIsSuccess回传接口,在设计业务逻辑接口传入,实现在界面回调得到请求数据和结果

private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            RequestIsSuccess requestIsSuccess = requestInterfMap.get(msg.arg1);

            Log.d("APIManager", " -=-=- handleMessage:  what:" + msg.what +
                    "  requestIsSuccess:" + requestIsSuccess);

            if (msg.what != REQUEST_RELOGIN && requestIsSuccess == null) return;
            switch (msg.what) {
                case REQUEST_SUCCESS_TRUE:
                    requestIsSuccess.isSuccess(true, true, msg.obj + "");
                    break;
                case REQUEST_SUCCESS_FALSE:
                    requestIsSuccess.isSuccess(true, false, msg.obj + "");
                    break;
                case REQUEST_FAILED:
                    requestIsSuccess.isSuccess(false, false, msg.obj + "");
                    break;
                case REQUEST_RELOGIN:
                    requestReLogin("登陆信息过期!请重新登陆!");
                    break;
            }
        }
    };

public interface RequestIsSuccess {
        void isSuccess(boolean isRequestSuccess, boolean isSuccess, String msg);
    }

在业务逻辑接口RequestIsSuccess回调使用的示例

// 定义业务逻辑接口
public Call<ResponseBody> uploadFile(String path, int fileType, RequestIsSuccess requestIsSuccess) {
        if (!checkIpPort()) return null;
        return request(requestIsSuccess, BroadManageController, uploadFile, path, fileType);
    }

// 发起retrofit请求
private Call<ResponseBody> request(RequestIsSuccess requestIsSuccess, String path, String apiPath, Object... objects) {
        requestMap.clear();
        int hashCode = requestIsSuccess.hashCode();
        requestInterfMap.put(hashCode, requestIsSuccess);
        switch (path + apiPath) {
        	case BroadManageController + uploadFile:
            	requestMap.put(Config.pathParam, objects[0]);
                requestMap.put(Config.fileTypeParam, objects[1]);
            break;
            ...
       }
       return retrofitEnqueue(hashCode, path, apiPath, apiInterface.request(path, apiPath, requestMap));
       }

在UI界面调用接口返回数据

APIManager.getInstance().uploadFile(path, fileType, (isRequestSuccess, isSuccess, msg) -> {
            Log.d("BroadCreateModel", " -=-=- getMediaIdEbmid:  isRequestSuccess:"
                    + isRequestSuccess + "  isSuccess:" + isSuccess + "  msg:" + msg);
            if (isRequestSuccess && isSuccess) {
                requestListener.callBack(new Gson().fromJson(msg, UploadMediaEntity.class));
            } else {
                requestListener.callBack(null);
            }
        });

public interface RequestListener {
        void callBack(Object o);
    }

多文件上传的接口

主要是请求接口设计现需要传入参数@Body MultipartBody multipartBody,其次在构造请求体时使用MediaType.parse指名是什么格式文件。

public APIManager uploadDataCollectFile(String areaIds, List<File> fileList, RequestIsSuccess requestIsSuccess) {
        String userName = SPUtils.getInstance().getString(SpConfig.USER_NAME);
        Log.d(TAG, "uploadDataCollectFile() areaIds:" + areaIds + ", userName:" + userName);
        if (!checkIpPort()) return this;
        int hashCode = requestIsSuccess.hashCode();
        requestInterfMap.put(hashCode, requestIsSuccess);

        MultipartBody.Builder builder = new MultipartBody.Builder();
        builder.setType(MultipartBody.FORM);
        RequestBody requestBody;
        String parse = "";
        for (File file : fileList) {
            uploadAudioFileMimeType(file.getName(), parse);
            uploadVideoFileMimeType(file.getName(), parse);
            if (file.getName().endsWith(".txt")) parse = "text/plain";

            requestBody = RequestBody.create(MediaType.parse(parse), file);
            builder.addFormDataPart("resource", file.getName(), requestBody);
        }
        builder.addFormDataPart("userName", userName);
        builder.addFormDataPart("areaIds", areaIds);

        MultipartBody multipartBody = builder.build();
        retrofitEnqueue(hashCode, UpCommandResourceController, add,
                apiInterface.uploadFiles(UpCommandResourceController, add, multipartBody));
        return this;
    }

public boolean checkIpPort() {
        boolean checkIP = Utils.checkIPAndPort(BASE_URL);
        // TODO BaseURL为空,需要重新登陆
        if (!checkIP) {
            Log.e(TAG, " -=-=- checkIpPort: IP错误!重新登陆!IP:" + BASE_URL + "  isTrue:" + checkIP);
            requestReLogin("IP 信息异常,请重新登陆");
        }
        return checkIP;
    }

Utils检查IP的接口

private static final String PREFIX_PATTERN = "((http://)|(https://))";
private static final String IP_FULL_PATTERN = 
"(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])"+"\\." +
"(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])" + "\\." +
"(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])" + "\\." + 
"(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])";
private static final String PORT_PATTERN = "([0-9]|[1-9]\\d{1,3}|[1-5]\\d{4}|6[0-4]\\d{4}|65[0-4]\\d{2}|655[0-2]\\d|6553[0-5])";
public static boolean checkIPAndPort(String ipAndPort) {
        String pattern = PREFIX_PATTERN + IP_FULL_PATTERN + ":" + PORT_PATTERN;
        return ipAndPort.matches(pattern);
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值