package org.aisen.wen.component.network.http; import android.text.TextUtils; import com.alibaba.fastjson.JSON; import com.squareup.okhttp.MediaType; import com.squareup.okhttp.MultipartBuilder; import com.squareup.okhttp.OkHttpClient; import com.squareup.okhttp.Request; import com.squareup.okhttp.RequestBody; import com.squareup.okhttp.Response; import com.squareup.okhttp.internal.Util; import org.aisen.wen.base.GlobalContext; import org.aisen.wen.component.network.biz.ABizLogic; import org.aisen.wen.component.network.setting.Setting; import org.aisen.wen.component.network.task.TaskException; import org.aisen.wen.support.utils.Logger; import org.aisen.wen.support.utils.SystemUtils; import java.io.ByteArrayInputStream; import java.io.IOException; import java.net.HttpURLConnection; import java.net.SocketTimeoutException; import java.util.Set; import java.util.concurrent.TimeUnit; import okio.Buffer; import okio.BufferedSink; import okio.Okio; import okio.Source; public class DefHttpUtility implements IHttpUtility { static String getTag(Setting action, String append) { return ABizLogic.getTag(action, append); } public final static int CONN_TIMEOUT = 30000; public final static int READ_TIMEOUT = 30000; private final static OkHttpClient mOkHttpClient = new OkHttpClient(); static { // 初始化OkHttpClient configOkHttpClient(CONN_TIMEOUT, READ_TIMEOUT); } public static void configOkHttpClient(int connTimeout, int socketTimeout) { if (mOkHttpClient != null) { mOkHttpClient.setConnectTimeout(connTimeout, TimeUnit.MILLISECONDS); mOkHttpClient.setReadTimeout(socketTimeout, TimeUnit.MILLISECONDS); } } @Override public <T> T doGet(HttpConfig config, Setting action, Params urlParams, Class<T> responseCls) throws TaskException { Request.Builder builder = createRequestBuilder(config, action, urlParams, "Get"); Request request = builder.build(); return executeRequest(request, responseCls, action, "Get"); } @Override public <T> T doPost(HttpConfig config, Setting action, Params urlParams, Params bodyParams, Object requestObj, Class<T> responseCls) throws TaskException { Request.Builder builder = createRequestBuilder(config, action, urlParams, "Post"); if (bodyParams != null) { String requestBodyStr = bodyParams.toURLQuery(); Logger.d(getTag(action, "Post"), requestBodyStr); builder.post(RequestBody.create(MediaType.parse("application/x-www-form-urlencoded;charset=UTF-8"), requestBodyStr)); } else if (requestObj != null) { String requestBodyStr = JSON.toJSONString(requestObj); Logger.d(getTag(action, "Post"), requestBodyStr); builder.post(RequestBody.create(MediaType.parse("application/json; charset=UTF-8"), requestBodyStr)); } return executeRequest(builder.build(), responseCls, action, "Post"); } @Override public <T> T doPostFiles(HttpConfig config, Setting action, Params urlParams, Params bodyParams, MultipartFile[] files, Class<T> responseCls) throws TaskException { String method = "doPostFiles"; Request.Builder builder = createRequestBuilder(config, action, urlParams, method); MultipartBuilder multipartBuilder = new MultipartBuilder(); multipartBuilder.type(MultipartBuilder.FORM); // 处理Body参数 if (bodyParams != null && bodyParams.getKeys().size() > 0) { for (String key : bodyParams.getKeys()) { String value = bodyParams.get(key); multipartBuilder.addFormDataPart(key, value); Logger.d(getTag(action, method), "BodyParam[%s, %s]", key, value); } } // 处理文件数据 if (files != null && files.length > 0) { for (MultipartFile file : files) { // 普通字节流 if (file.getBytes() != null) { multipartBuilder.addFormDataPart(file.getKey(), file.getKey(), createRequestBody(file)); Logger.d(getTag(action, method), "Multipart bytes, length = " + file.getBytes().length); } // 文件 else if (file.getFile() != null) { multipartBuilder.addFormDataPart(file.getKey(), file.getFile().getName(), createRequestBody(file)); Logger.d(getTag(action, method), "Multipart file, name = %s, path = %s", file.getFile().getName(), file.getFile().getAbsolutePath()); } } } RequestBody requestBody = multipartBuilder.build(); builder.post(requestBody); return executeRequest(builder.build(), responseCls, action, method); } private Request.Builder createRequestBuilder(HttpConfig config, Setting action, Params urlParams, String method) throws TaskException { // 是否有网络连接 if (GlobalContext.getInstance() != null && SystemUtils.getNetworkType(GlobalContext.getInstance()) == SystemUtils.NetWorkType.none) { Logger.w(getTag(action, method), "没有网络连接"); throw new TaskException(TaskException.TaskError.noneNetwork.toString()); } String url = (config.baseUrl + action.getValue() + (urlParams == null ? "" : "?" + urlParams.toURLQuery())).replaceAll(" ", ""); Logger.d(getTag(action, method), url); Request.Builder builder = new Request.Builder(); builder.url(url); // add Cookie if (!TextUtils.isEmpty(config.cookie)) { builder.header("Cookie", config.cookie); Logger.d(getTag(action, method), "Cookie = " + config.cookie); } // add header if (config.headerMap.size() > 0) { Set<String> keySet = config.headerMap.keySet(); for (String key : keySet) { builder.addHeader(key, config.headerMap.get(key)); Logger.d(getTag(action, method), "Header[%s, %s]", key, config.headerMap.get(key)); } } return builder; } private <T> T executeRequest(Request request, Class<T> responseCls, Setting action, String method) throws TaskException { try { OkHttpClient okHttpClient = getOkHttpClient(); if (okHttpClient == null) { okHttpClient = mOkHttpClient; } Response response = okHttpClient.newCall(request).execute(); Logger.w(getTag(action, method), "Http-code = %d", response.code()); if (!(response.code() == HttpURLConnection.HTTP_OK || response.code() == HttpURLConnection.HTTP_PARTIAL)) { String responseStr = response.body().string(); if (Logger.DEBUG) { Logger.w(getTag(action, method), responseStr); } TaskException.checkResponse(responseStr); throw new TaskException(TaskException.TaskError.timeout.toString()); } else { String responseStr = response.body().string(); Logger.v(getTag(action, method), "Response = %s", responseStr); return parseResponse(responseStr, responseCls); } } catch (SocketTimeoutException e) { Logger.printExc(DefHttpUtility.class, e); Logger.w(getTag(action, method), e + ""); throw new TaskException(TaskException.TaskError.timeout.toString()); } catch (IOException e) { Logger.printExc(DefHttpUtility.class, e); Logger.w(getTag(action, method), e + ""); throw new TaskException(TaskException.TaskError.timeout.toString()); } catch (TaskException e) { Logger.printExc(DefHttpUtility.class, e); Logger.w(getTag(action, method), e + ""); throw e; } catch (Exception e) { Logger.printExc(DefHttpUtility.class, e); Logger.w(getTag(action, method), e + ""); throw new TaskException(TaskException.TaskError.resultIllegal.toString()); } } protected <T> T parseResponse(String resultStr, Class<T> responseCls) throws TaskException { if (responseCls.getSimpleName().equals("String")) return (T) resultStr; T result = JSON.parseObject(resultStr, responseCls); return result; } protected OkHttpClient getOkHttpClient() { return null; } private static RequestBody createRequestBody(final MultipartFile file) { return new RequestBody() { @Override public MediaType contentType() { return MediaType.parse(file.getContentType()); } @Override public long contentLength() throws IOException { return file.getBytes() != null ? file.getBytes().length : file.getFile().length(); } @Override public void writeTo(BufferedSink sink) throws IOException { Source source; if (file.getFile() != null) { source = Okio.source(file.getFile()); } else { source = Okio.source(new ByteArrayInputStream(file.getBytes())); } OnMultiFileProgress onFileProgress = file.getOnProgress(); if (onFileProgress != null) { try { long contentLength = contentLength(); long writeLen = 0; long readLen = -1; Buffer buffer = new Buffer(); long MIN_PROGRESS_STEP = 65536; long MIN_PROGRESS_TIME = 300; long mLastUpdateBytes = 0; long mLastUpdateTime = 0l; while ((readLen = source.read(buffer, 8 * 1024)) != -1) { sink.write(buffer, readLen); writeLen += readLen; long now = System.currentTimeMillis(); if (((writeLen - mLastUpdateBytes) > MIN_PROGRESS_STEP && (now - mLastUpdateTime) > MIN_PROGRESS_TIME) || writeLen == contentLength) { onFileProgress.onProgress(writeLen, contentLength); mLastUpdateBytes = writeLen; mLastUpdateTime = now; } } } catch (IOException e) { Logger.printExc(DefHttpUtility.class, e); throw e; } finally { Util.closeQuietly(source); } } else { try { sink.writeAll(source); } catch (IOException e) { Logger.printExc(DefHttpUtility.class, e); throw e; } finally { Util.closeQuietly(source); } } } }; } }