docs: public UploadResult uploadFile(String path, String fileType)
              throws APIConnectionException, APIRequestException {
          Preconditions.checkArgument(null != path, "filename is necessary");
          Preconditions.checkArgument(fileType.equals("image") || fileType.equals("file") || fileType.equals("voice"), "Illegal file type!");
          File file = new File(path);
          if (file.exists() && file.isFile()) {
              long fileSize = file.length();
              if (fileSize > 8 * 1024 * 1024) {
                  throw new IllegalArgumentException("File size should not larger than 8M");
              }
              try {
                  // 换行符
                  final String newLine = "\r\n";
                  final String boundaryPrefix = "--";
                  // 定义数据分隔线
                  String BOUNDARY = "========7d4a6d158c9";
                  URL url = new URL(_baseUrl + resourcePath + "?type=" + fileType);
                  HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                  conn.setRequestMethod("POST");
                  conn.setDoOutput(true);
                  conn.setDoInput(true);
                  conn.setUseCaches(false);
                  conn.setRequestProperty("connection", "Keep-Alive");
                  conn.setRequestProperty("Charset", "UTF-8");
                  conn.setRequestProperty("Authorization", this.authCode);
                  conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY);
                  OutputStream out = new DataOutputStream(conn.getOutputStream());
                  StringBuilder sb = new StringBuilder();
                  sb.append(boundaryPrefix);
                  sb.append(BOUNDARY);
                  sb.append(newLine);
                  sb.append("Content-Disposition: form-data;name=\"" + fileType + "\";filename=\"" + path + "\"" + newLine);
                  sb.append("Content-Type:application/octet-stream");
                  // 参数头设置完以后需要两个换行，然后才是参数内容
                  sb.append(newLine);
                  sb.append(newLine);
                  out.write(sb.toString().getBytes());
                  DataInputStream dataInputStream = new DataInputStream(new FileInputStream(file));
                  byte[] bufferOut = new byte[1024];
                  int bytes = 0;
                  while ((bytes = dataInputStream.read(bufferOut)) != -1) {
                      out.write(bufferOut, 0, bytes);
                  }
                  out.write(newLine.getBytes());
                  dataInputStream.close();
                  // 定义最后数据分隔线，即--加上BOUNDARY再加上--。
                  byte[] end_data = (newLine + boundaryPrefix + BOUNDARY + boundaryPrefix + newLine)
                          .getBytes();
                  // 写上结尾标识
                  out.write(end_data);
                  out.flush();
                  out.close();
                  LOG.debug("Send request - POST"  + " " + url);
  
                  int status1 = conn.getResponseCode();
                  StringBuffer stringBuffer = new StringBuffer();
                  InputStream in = null;
                  if(status1 / 100 == 2) {
                      in = conn.getInputStream();
                  } else {
                      in = conn.getErrorStream();
                  }
                  if(null != in) {
                      InputStreamReader responseContent = new InputStreamReader(in, "UTF-8");
                      char[] quota = new char[1024];
  
                      int remaining;
                      while((remaining = responseContent.read(quota)) > 0) {
                          stringBuffer.append(quota, 0, remaining);
                      }
                  }
                  ResponseWrapper wrapper = new ResponseWrapper();
                  String responseContent1 = stringBuffer.toString();
                  wrapper.responseCode = status1;
                  wrapper.responseContent = responseContent1;
                  String quota1 = conn.getHeaderField("X-Rate-Limit-Limit");
                  String remaining1 = conn.getHeaderField("X-Rate-Limit-Remaining");
                  String reset = conn.getHeaderField("X-Rate-Limit-Reset");
                  wrapper.setRateLimit(quota1, remaining1, reset);
                  if(status1 >= 200 && status1 < 300) {
                      LOG.debug("Succeed to get response OK - responseCode:" + status1);
                      LOG.debug("Response Content - " + responseContent1);
                  } else {
                      if(status1 < 300 || status1 >= 400) {
                          LOG.warn("Got error response - responseCode:" + status1 + ", responseContent:" + responseContent1);
                          wrapper.setErrorObject();
                          throw new APIRequestException(wrapper);
                      }
  
                      LOG.warn("Normal response but unexpected - responseCode:" + status1 + ", responseContent:" + responseContent1);
                  }
                  return UploadResult.fromResponse(wrapper, UploadResult.class);
              } catch (Exception e) {
                  e.printStackTrace();
              }
          } else {
              throw new IllegalArgumentException("File name is invalid, please check again");
          }
          return null;
      }