content: /*
   * 微信公众平台(JAVA) SDK
   *
   * Copyright (c) 2014, Ansitech Network Technology Co.,Ltd All rights reserved.
   * 
   * http://www.weixin4j.org/
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  package org.weixin4j.http;
  
  import com.alibaba.fastjson.JSONObject;
  import org.weixin4j.model.media.Attachment;
  import java.io.BufferedInputStream;
  import java.io.BufferedReader;
  import java.io.DataInputStream;
  import java.io.DataOutputStream;
  import java.io.File;
  import java.io.FileInputStream;
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.InputStreamReader;
  import java.io.OutputStream;
  import java.net.HttpURLConnection;
  import java.net.URL;
  import java.security.KeyManagementException;
  import java.security.NoSuchAlgorithmException;
  import java.security.NoSuchProviderException;
  import org.weixin4j.Configuration;
  import org.weixin4j.WeixinException;
  
  /**
   * HttpClient业务
   *
   * @author yangqisheng
   * @since 0.0.1
   */
  public class HttpClient implements java.io.Serializable {
  
      private static final int OK = 200;  // OK: Success!
      private static final int ConnectionTimeout = Configuration.getConnectionTimeout();
      private static final int ReadTimeout = Configuration.getReadTimeout();
      private static final String DEFAULT_CHARSET = "UTF-8";
      private static final String _GET = "GET";
      private static final String _POST = "POST";
  
      /**
       * Get 请求
       *
       * @param url 请求地址
       * @return 输出流对象
       * @throws org.weixin4j.WeixinException 微信操作异常
       */
      public Response get(String url) throws WeixinException {
          return httpRequest(url, _GET, null);
      }
  
      /**
       * 上传文件
       *
       * @param url 上传地址
       * @param file 上传文件对象
       * @return 服务器上传响应结果
       * @throws IOException IO异常
       * @throws NoSuchAlgorithmException 算法异常
       * @throws NoSuchProviderException 私钥异常
       * @throws KeyManagementException 密钥异常
       */
      public String upload(String url, File file) throws IOException,
              NoSuchAlgorithmException, NoSuchProviderException,
              KeyManagementException {
          HttpURLConnection http = null;
          StringBuffer bufferRes = new StringBuffer();
          try {
              // 定义数据分隔线 
              String BOUNDARY = "----WebKitFormBoundaryiDGnV9zdZA1eM1yL";
              //创建https请求连接
              http = getHttpURLConnection(url);
              //设置header和ssl证书
              setHttpHeader(http, _POST);
              //不缓存
              http.setUseCaches(false);
              //保持连接
              http.setRequestProperty("connection", "Keep-Alive");
              //设置文档类型
              http.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY);
  
              //定义输出流
              OutputStream out = null;
              //定义输入流
              DataInputStream dataInputStream;
              try {
                  out = new DataOutputStream(http.getOutputStream());
                  byte[] end_data = ("\r\n--" + BOUNDARY + "--\r\n").getBytes();// 定义最后数据分隔线  
                  StringBuilder sb = new StringBuilder();
                  sb.append("--");
                  sb.append(BOUNDARY);
                  sb.append("\r\n");
                  sb.append("Content-Disposition: form-data;name=\"media\";filename=\"").append(file.getName()).append("\"\r\n");
                  sb.append("Content-Type:application/octet-stream\r\n\r\n");
                  byte[] data = sb.toString().getBytes();
                  out.write(data);
                  //读取文件流
                  dataInputStream = new DataInputStream(new FileInputStream(file));
                  int bytes;
                  byte[] bufferOut = new byte[1024];
                  while ((bytes = dataInputStream.read(bufferOut)) != -1) {
                      out.write(bufferOut, 0, bytes);
                  }
                  out.write("\r\n".getBytes()); //多个文件时，二个文件之间加入这个  
                  dataInputStream.close();
                  out.write(end_data);
                  out.flush();
              } finally {
                  if (out != null) {
                      out.close();
                  }
              }
  
              // 定义BufferedReader输入流来读取URL的响应  
              InputStream ins = null;
              try {
                  ins = http.getInputStream();
                  BufferedReader read = new BufferedReader(new InputStreamReader(ins, "UTF-8"));
                  String valueString;
                  bufferRes = new StringBuffer();
                  while ((valueString = read.readLine()) != null) {
                      bufferRes.append(valueString);
                  }
              } finally {
                  if (ins != null) {
                      ins.close();
                  }
              }
          } finally {
              if (http != null) {
                  // 关闭连接
                  http.disconnect();
              }
          }
          return bufferRes.toString();
      }
  
      /**
       * 下载附件
       *
       * @param url 附件地址
       * @return 附件对象
       * @throws IOException IO异常
       */
      public Attachment download(String url) throws IOException {
          Attachment attachment = new Attachment();
          URL _url = new URL(url);
          HttpURLConnection http = (HttpURLConnection) _url.openConnection();
          //设置头
          setHttpHeader(http, "GET");
          if (http.getContentType().equalsIgnoreCase("text/plain")) {
              // 定义BufferedReader输入流来读取URL的响应  
              InputStream in = http.getInputStream();
              BufferedReader read = new BufferedReader(new InputStreamReader(in, "UTF-8"));
              String valueString;
              StringBuilder bufferRes = new StringBuilder();
              while ((valueString = read.readLine()) != null) {
                  bufferRes.append(valueString);
              }
              in.close();
              attachment.setError(bufferRes.toString());
          } else if (http.getContentType().contains("application/json")) {
              // 定义BufferedReader输入流来读取URL的响应  
              InputStream in = http.getInputStream();
              BufferedReader read = new BufferedReader(new InputStreamReader(in, "UTF-8"));
              String valueString;
              StringBuilder bufferRes = new StringBuilder();
              while ((valueString = read.readLine()) != null) {
                  bufferRes.append(valueString);
              }
              in.close();
              String jsonString = bufferRes.toString();
              JSONObject result = JSONObject.parseObject(jsonString);
              if (result.containsKey("errcode") && result.getIntValue("errcode") != 0) {
                  attachment.setError(result.getString("errmsg"));
              } else {
                  //未知格式
                  attachment.setError(jsonString);
              }
          } else {
              BufferedInputStream bis = new BufferedInputStream(http.getInputStream());
              String ds = http.getHeaderField("Content-disposition");
              String fullName = ds.substring(ds.indexOf("filename=\"") + 10, ds.length() - 1);
              String relName = fullName.substring(0, fullName.lastIndexOf("."));
              String suffix = fullName.substring(relName.length() + 1);
  
              attachment.setFullName(fullName);
              attachment.setFileName(relName);
              attachment.setSuffix(suffix);
              attachment.setContentLength(http.getHeaderField("Content-Length"));
              attachment.setContentType(http.getHeaderField("Content-Type"));
  
              attachment.setFileStream(bis);
          }
          return attachment;
      }
  
      /**
       * 获取http请求连接
       *
       * @param url 连接地址
       * @return http连接对象
       * @throws IOException IO异常
       */
      private HttpURLConnection getHttpURLConnection(String url) throws IOException {
          URL urlGet = new URL(url);
          HttpURLConnection con = (HttpURLConnection) urlGet.openConnection();
          return con;
      }
  
      /**
       * 通过http协议请求url
       *
       * @param url 提交地址
       * @param method 提交方式
       * @param postData 提交数据
       * @return 响应流
       * @throws org.weixin4j.WeixinException 微信操作异常
       */
      private Response httpRequest(String url, String method, String postData)
              throws WeixinException {
          Response res = null;
          OutputStream output;
          HttpURLConnection http;
          try {
              //创建https请求连接
              http = getHttpURLConnection(url);
              //判断https是否为空，如果为空返回null响应
              if (http != null) {
                  //设置Header信息
                  setHttpHeader(http, method);
                  //判断是否需要提交数据
                  if (method.equals(_POST) && null != postData) {
                      //讲参数转换为字节提交
                      byte[] bytes = postData.getBytes(DEFAULT_CHARSET);
                      //设置头信息
                      http.setRequestProperty("Content-Length", Integer.toString(bytes.length));
                      //开始连接
                      http.connect();
                      //获取返回信息
                      output = http.getOutputStream();
                      output.write(bytes);
                      output.flush();
                      output.close();
                  } else {
                      //开始连接
                      http.connect();
                  }
                  //创建输出对象
                  res = new Response(http);
                  //获取响应代码
                  if (res.getStatus() == OK) {
                      return res;
                  }
              }
          } catch (IOException ex) {
              throw new WeixinException(ex.getMessage(), ex);
          }
          return res;
      }
  
      private void setHttpHeader(HttpURLConnection httpUrlConnection, String method)
              throws IOException {
          //设置header信息
          httpUrlConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
          //设置User-Agent信息
          httpUrlConnection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.146 Safari/537.36");
          //设置可接受信息
          httpUrlConnection.setDoOutput(true);
          //设置可输入信息
          httpUrlConnection.setDoInput(true);
          //设置请求方式
          httpUrlConnection.setRequestMethod(method);
          //设置连接超时时间
          if (ConnectionTimeout > 0) {
              httpUrlConnection.setConnectTimeout(ConnectionTimeout);
          } else {
              //默认10秒超时
              httpUrlConnection.setConnectTimeout(10000);
          }
          //设置请求超时
          if (ReadTimeout > 0) {
              httpUrlConnection.setReadTimeout(ReadTimeout);
          } else {
              //默认10秒超时
              httpUrlConnection.setReadTimeout(10000);
          }
          //设置编码
          httpUrlConnection.setRequestProperty("Charsert", "UTF-8");
      }
  }
  