123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323 |
- package cn.com.qmth.examcloud.web.upyun;
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.FileNotFoundException;
- import java.io.InputStream;
- import java.security.InvalidKeyException;
- import java.security.NoSuchAlgorithmException;
- import java.security.SignatureException;
- import java.text.SimpleDateFormat;
- import java.util.Base64;
- import java.util.Calendar;
- import java.util.Locale;
- import java.util.Map;
- import java.util.TimeZone;
- import java.util.concurrent.TimeUnit;
- import javax.crypto.Mac;
- import javax.crypto.spec.SecretKeySpec;
- import org.apache.commons.compress.utils.IOUtils;
- import org.apache.commons.lang3.StringUtils;
- import org.apache.http.HttpStatus;
- import org.apache.http.client.config.RequestConfig;
- import org.apache.http.client.methods.CloseableHttpResponse;
- import org.apache.http.client.methods.HttpDelete;
- import org.apache.http.client.methods.HttpPut;
- import org.apache.http.entity.InputStreamEntity;
- import org.apache.http.impl.client.CloseableHttpClient;
- import org.apache.http.impl.client.HttpClients;
- import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
- import org.apache.http.util.EntityUtils;
- import com.google.common.collect.Maps;
- import cn.com.qmth.examcloud.commons.exception.ExamCloudRuntimeException;
- import cn.com.qmth.examcloud.commons.exception.StatusException;
- import cn.com.qmth.examcloud.commons.logging.ExamCloudLog;
- import cn.com.qmth.examcloud.commons.logging.ExamCloudLogFactory;
- import cn.com.qmth.examcloud.commons.util.MD5;
- /**
- * upyun client
- *
- * @author WANGWEI
- * @date 2018年11月21日
- * @Copyright (c) 2018-? http://qmth.com.cn All Rights Reserved.
- */
- public class UpYunClient {
- protected ExamCloudLog log = ExamCloudLogFactory.getLog(this.getClass());
- /**
- * 空间名
- */
- protected String bucketName = null;
- /**
- * 操作员名
- */
- protected String userName = null;
- /**
- * 操作员密码
- */
- protected String password = null;
- protected String md5Password = null;
- public static final String API_DOMAIN = "v0.api.upyun.com";
- private static final String MKDIR = "mkdir";
- private final String METHOD_PUT = "PUT";
- private final String METHOD_DELETE = "DELETE";
- private final String DATE = "Date";
- private final String AUTHORIZATION = "Authorization";
- private final String SEPARATOR = "/";
- private static CloseableHttpClient httpclient;
- private static RequestConfig requestConfig;
- private String domain;
- static {
- PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(10,
- TimeUnit.SECONDS);
- cm.setValidateAfterInactivity(2000);
- cm.setMaxTotal(1000);
- cm.setDefaultMaxPerRoute(1000);
- httpclient = HttpClients.custom().setConnectionManager(cm).disableAutomaticRetries()
- .build();
- requestConfig = RequestConfig.custom().setConnectionRequestTimeout(10000)
- .setSocketTimeout(10000).setConnectTimeout(10000).build();
- }
- /**
- * 构造函数
- *
- * @param bucketName
- * @param userName
- * @param password
- */
- public UpYunClient(String bucketName, String userName, String password, String domain) {
- this.bucketName = bucketName;
- this.userName = userName;
- this.password = password;
- this.domain = domain;
- this.md5Password = MD5.encrypt32(password);
- }
- /**
- * 创建又拍云签名
- *
- * @author WANGWEI
- * @param filePath
- * @return
- */
- public UpYunSign buildUpYunSign(String filePath) {
- String path = formatPath(filePath);
- String url = "https://" + API_DOMAIN + path;
- Map<String, String> headers = Maps.newHashMap();
- String date = getDate();
- String authorization = null;
- try {
- authorization = sign(userName, md5Password, METHOD_PUT, path, date, "", "");
- } catch (Exception e) {
- throw new StatusException("100005", "[upyun]. fail to build sign", e);
- }
- headers.put(AUTHORIZATION, authorization);
- headers.put(DATE, date);
- headers.put(MKDIR, "true");
- UpYunSign sign = new UpYunSign();
- sign.setUrl(url);
- sign.setHeaders(headers);
- return sign;
- }
- /**
- * 上传文件
- *
- * @author WANGWEI
- * @param filePath
- * @param file
- * @return
- */
- public UpYunPathInfo writeFile(String filePath, File file) {
- InputStream in = null;
- try {
- in = new FileInputStream(file);
- return writeFile(filePath, in);
- } catch (FileNotFoundException e) {
- throw new ExamCloudRuntimeException(e);
- } finally {
- IOUtils.closeQuietly(in);
- }
- }
- /**
- * 上传文件
- *
- * @author WANGWEI
- * @param filePath
- * @param in
- * @return
- */
- public UpYunPathInfo writeFile(String filePath, InputStream in) {
- String path = formatPath(filePath);
- String url = "https://" + API_DOMAIN + path;
- HttpPut httpPut = new HttpPut(url);
- httpPut.setConfig(UpYunClient.requestConfig);
- CloseableHttpResponse response = null;
- long s = System.currentTimeMillis();
- try {
- String date = getDate();
- String authorization = sign(userName, md5Password, METHOD_PUT, path, date, "", "");
- httpPut.addHeader(AUTHORIZATION, authorization);
- httpPut.addHeader(DATE, date);
- httpPut.addHeader(MKDIR, "true");
- httpPut.setEntity(new InputStreamEntity(in));
- response = httpclient.execute(httpPut);
- int statusCode = response.getStatusLine().getStatusCode();
- if (HttpStatus.SC_OK != statusCode) {
- log.error("[upyun error] " + EntityUtils.toString(response.getEntity(), "UTF-8"));
- throw new StatusException("100001", "[upyun]. fail to write file");
- }
- } catch (StatusException e) {
- throw e;
- } catch (Exception e) {
- throw new ExamCloudRuntimeException(e);
- } finally {
- IOUtils.closeQuietly(in);
- IOUtils.closeQuietly(response);
- httpPut.releaseConnection();
- }
- if (log.isDebugEnabled()) {
- log.debug("[upyun]. write file. path=" + path + "; cost "
- + (System.currentTimeMillis() - s) + " ms.");
- }
- String fileUrl = this.domain + filePath;
- return new UpYunPathInfo(fileUrl, filePath);
- }
- /**
- * 删除文件
- *
- * @author WANGWEI
- * @param filePath
- * @return
- */
- public void deleteFile(String filePath) {
- String path = formatPath(filePath);
- String url = "https://" + API_DOMAIN + path;
- HttpDelete httpDelete = new HttpDelete(url);
- httpDelete.setConfig(UpYunClient.requestConfig);
- CloseableHttpResponse response = null;
- long s = System.currentTimeMillis();
- try {
- String date = getDate();
- String authorization = sign(userName, md5Password, METHOD_DELETE, path, date, "", "");
- httpDelete.addHeader(AUTHORIZATION, authorization);
- httpDelete.addHeader(DATE, date);
- response = httpclient.execute(httpDelete);
- int statusCode = response.getStatusLine().getStatusCode();
- if (HttpStatus.SC_OK != statusCode) {
- log.error("[upyun error] " + EntityUtils.toString(response.getEntity(), "UTF-8"));
- throw new StatusException("100002", "[upyun]. fail to delete file");
- }
- } catch (StatusException e) {
- throw e;
- } catch (Exception e) {
- throw new ExamCloudRuntimeException(e);
- } finally {
- IOUtils.closeQuietly(response);
- httpDelete.releaseConnection();
- }
- if (log.isDebugEnabled()) {
- log.debug("[upyun]. delete file. path=" + path + "; cost "
- + (System.currentTimeMillis() - s) + " ms.");
- }
- }
- /**
- * 格式化路径参数
- * <p>
- * 最终构成的格式:"/空间名/文件路径"
- *
- * @param path
- * 目录路径或文件路径
- * @return 格式化后的路径
- */
- private String formatPath(String path) {
- if (StringUtils.isNotBlank(path)) {
- // 去除前后的空格
- path = path.trim();
- // 确保路径以"/"开头
- if (!path.startsWith(SEPARATOR)) {
- return SEPARATOR + bucketName + SEPARATOR + path;
- }
- }
- return SEPARATOR + bucketName + path;
- }
- private String getDate() {
- Calendar calendar = Calendar.getInstance();
- SimpleDateFormat dateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z",
- Locale.US);
- dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
- return dateFormat.format(calendar.getTime());
- }
- private byte[] hashHmac(String data, String key)
- throws SignatureException, NoSuchAlgorithmException, InvalidKeyException {
- SecretKeySpec signingKey = new SecretKeySpec(key.getBytes(), "HmacSHA1");
- Mac mac = Mac.getInstance("HmacSHA1");
- mac.init(signingKey);
- return mac.doFinal(data.getBytes());
- }
- private String sign(String key, String secret, String method, String uri, String date,
- String policy, String md5) throws Exception {
- String value = method + "&" + uri + "&" + date;
- if (policy != null && policy.length() > 0) {
- value = value + "&" + policy;
- }
- if (md5 != null && md5.length() > 0) {
- value = value + "&" + md5;
- }
- byte[] hmac = hashHmac(value, secret);
- String sign = Base64.getEncoder().encodeToString(hmac);
- return "UPYUN " + key + ":" + sign;
- }
- }
|