百度BOS调用记录
百度BOS调用记录
之前在工作中遇到了需要使用百度bos的场景,记录一下代码
百度bos工具类
package com.cccp.common.baidubos;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.UUID;
import org.apache.log4j.Logger;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.ISODateTimeFormat;
import java.io.InputStream;
/**
*
* <p>Title: [百度bos工具] </p>
* <p>Description: [百度bos工具]</p>
* @author zhengyingjun
* @update [修改人] [修改时间]
* @version v1.0
*/
public class BaiduBosUtil {
/**
* 日志
*/
private static Logger logger = Logger.getLogger(BaiduBosUtil.class);
/**
* UTC时间获取
*/
private static final DateTimeFormatter Iso8601DateFormat = ISODateTimeFormat.dateTimeNoMillis().withZone(DateTimeZone.UTC);
/**
* 是否开启百度bos功能,在配置文件中配置,默认为false,在baidu_bos.conf 中修改
*/
private static boolean baidubosStart = false;
/**
* 百度签名ak
*/
private static String AccessKeyId = "";
/**
* 百度签名sk
*/
private static String SecretAccessKey = "";
/**
* host地址
*/
private static String Host = "";
private static Config config = null;
private static InputStream stream;
public static String formatIso8601Date(){
return Iso8601DateFormat.print(new DateTime(new Date()));
}
static {
//判断properties集合对象是否为空,为空则创建一个集合对象
properties = new Properties();
/*
* 由于我们会调用load方法,而load方法低层抛出了一个IOException异常,此异常为编译时期异常所以,
* 我们调用load方法时,需要处理低层抛过来的异常*/
try {
//创建一个InputStream字节输入流对象,用于接收baidu_bos.properties配置文件中的配置参数
stream = BaiduBosUtil.class.getClassLoader().getResourceAsStream("baidu_bos.properties");
//properties集合对象调用load()方法,将配置参数加载到properties集合中
properties.load(stream);
// 读取配置中百度授权信息-此处代码根据实际情况编写
baidubosStart = Boolean.parseBoolean(properties.getProperty("bos_start"));
AccessKeyId = properties.getProperty("accesskeyid");
SecretAccessKey = properties.getProperty("secretaccesskey");
Host = properties.getProperty("host");
}catch(Exception e){
baidubosStart = false;
}
}
/**
*
* <p>Discription:从百度bos下载文件-http 形式
*</p>
* @param filesuffix 文件拓展名
* @param bucket_name bucket_name bucket名称 根据百度控制台实际情况填写
* @return
* @author zhengyingjun 2021-1-19
* @update [修改人] [修改时间] [变更描述]
*/
public byte[] download(String bucket_name,String filesuffix){
if(!baidubosStart){
logger.error("百度BOS功能未开启");
return null;
}
byte[] file = null;
try {
String uri = "/v1/"+bucket_name+"/"+filesuffix;
Map<String, String> mapPrams = new HashMap<String, String>();
String timestamps = formatIso8601Date();
mapPrams.put("method", "POST");
mapPrams.put("timestamp",timestamps);
mapPrams.put("expirationPeriodInSeconds", "1800");
mapPrams.put("bce-auth", "bce-auth-v1");
mapPrams.put("SecretAccessKey", SecretAccessKey);
mapPrams.put("accessKeyId", AccessKeyId);
mapPrams.put("uri", uri);
SortedMap<String, String> parms = new TreeMap<String, String>();
parms.put("host", Host);
parms.put("x-bce-date", timestamps.replaceAll(":", "%3A"));
Map<String,String> headers = new HashMap<String, String>();
headers.put("Host", Host);
headers.put("x-bce-date", timestamps);
IAMUtil iamUtil = new IAMUtil();
String authorizationStr = "";
try {
authorizationStr = iamUtil.createAuthorization(mapPrams, parms);
headers.put("Authorization", authorizationStr);
} catch (Exception e1) {
e1.printStackTrace();
logger.error("[post请求百度BOS生成认证字符串 authorization失败]");
}
String url = "http://"+Host+uri;
file = HttpUtil.GET_WITHHEADERS(url, parms, headers);
logger.info("BOS下载成功!");
} catch (Exception e) {
logger.error("百度BOS下载出错", e);
e.printStackTrace();
}
return file;
}
/**
*
* <p>Discription:上传文件到百度bos指定bucket中-http</p>
* @param bucket_name 存储的bucket名称,按百度控制台实际情况输入
* @param filebytes 文件
* @return
* @author zhengyingjun 2021-1-19
* @update [修改人] [修改时间] [变更描述]
*/
public String[] upload(String bucket_name, byte[] filebytes){
if(!baidubosStart){
logger.error("百度BOS功能未开启");
return null;
}
String[] result = null;
try{
String uuid = getUUID();
String uri = "/v1/"+bucket_name+"/"+uuid;
Map<String, String> mapPrams = new HashMap<String, String>();
String timestamps = formatIso8601Date();
mapPrams.put("method", "POST");
mapPrams.put("timestamp",timestamps);
mapPrams.put("expirationPeriodInSeconds", "1800");
mapPrams.put("bce-auth", "bce-auth-v1");
mapPrams.put("SecretAccessKey", SecretAccessKey);
mapPrams.put("accessKeyId", AccessKeyId);
mapPrams.put("uri", uri);
SortedMap<String, String> parms = new TreeMap<String, String>();
parms.put("host", Host);
parms.put("x-bce-date", timestamps.replaceAll(":", "%3A"));
Map<String,String> headers = new HashMap<String, String>();
headers.put("Host", Host);
headers.put("x-bce-date", timestamps);
IAMUtil iamUtil = new IAMUtil();
String authorizationStr = "";
try {
authorizationStr = iamUtil.createAuthorization(mapPrams, parms);
headers.put("Authorization", authorizationStr);
} catch (Exception e1) {
e1.printStackTrace();
logger.error("[post请求百度BOS生成认证字符串 authorization失败]");
}
String url = "http://"+Host+uri;
byte[] res = HttpUtil.POST_BYTES(url, filebytes, headers);
if(res!=null){
logger.info("BOS上传成功! Bucket: "+bucket_name+" filekey:"+uuid);
result = new String[2];
result[0]= bucket_name;
result[1]= uuid;
}
}catch(Exception e){
logger.error("百度BOS上传出错", e);
e.printStackTrace();
}
return result;
}
public static String getUUID(){
return UUID.randomUUID().toString().replaceAll("-", "");
}
}
http请求工具类
package com.cccp.common.baidubos;
import org.apache.http.HttpEntity;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.utils.HttpClientUtils;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.config.SocketConfig;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.ByteArrayEntity;
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.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import org.apache.log4j.Logger;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.net.URISyntaxException;
import java.nio.charset.Charset;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
*
* <p>Title: [http请求工具类] </p>
* @author zhengyingjun
* @update [修改人] [修改时间]
* @version v2.0
*/
public class HttpUtil {
private static Logger logger = Logger.getLogger(HttpUtil.class);
/**
* 连接超时时间(与服务器建立连接)(20s)
*/
private static final int CONNECTION_TIMEOUT_MS = 5000;
/**
* 读取数据(socket读取数据包之间)超时时间(20s)
*/
private static final int SO_TIMEOUT_MS = 5000;
/**
* 连接池最大连接数
*/
private static final int POOL_MAX_SIZE = 2000;
/**
* 对于某一个目标地址最大的连接数
*/
private static final int POOL_MAX_PEER_ROUTE = 400;
/**
* UserAgent定义
*/
private static final String userAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:53.0) Gecko/20100101 Firefox/53.0";
/**
* JSON格式数据编码
*/
public static final String CONTENT_TYPE_JSON = "application/json";
/**
* 键值对字符串数据格式
*/
private static final String CONTENT_TYPE_FORM = "application/x-www-form-urlencoded";
/**
* 键值对字符串数据格式
*/
private static final String CONTENT_TYPE_FORM_UTF8 = "application/x-www-form-urlencoded;charset=utf-8";
/**
* 二进制数据格式
*/
private static final String CONTENT_TYPE_OCTET_STREAM = "application/octet-stream";
/**
* xml格式数据编码
*/
private static final String CONTENT_TYPE_XML = "application/xml";
/**
* 主要用于十六进制数据
*/
private static final char[] HEXDIGITS = "0123456789abcdef".toCharArray();
/**
* httpclient读取内容时使用的字符集
*/
public static final String CONTENT_CHARSET = "UTF-8";
public static final String CONTENT_CHARSET_GBK = "GBK";
public static final Charset UTF_8 = Charset.forName("UTF-8");
/**
* 使用http连接池管理
*/
private static PoolingHttpClientConnectionManager connManager = null;
/**
* httpclient是线程安全,共享一个实例接口
*/
private static CloseableHttpClient client = null;
static {
try {
SSLContext context = SSLContext.getInstance("TLSv1.2");
X509TrustManager tm = new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] xcs, String string) throws CertificateException {}
public void checkServerTrusted(X509Certificate[] xcs, String string) throws CertificateException {}
public X509Certificate[] getAcceptedIssuers() {return null;}
};
context.init(null, new TrustManager[] { tm }, null);
HostnameVerifier verifier = SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER;
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(context, verifier);
Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.INSTANCE)
.register("https", sslsf)
.build();
// 初始化连接池
connManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
// Create socket configuration( nginx 默认也开启这个选项)
SocketConfig socketConfig = SocketConfig.custom().setTcpNoDelay(true).build();
connManager.setDefaultSocketConfig(socketConfig);
connManager.setMaxTotal(POOL_MAX_SIZE);
connManager.setDefaultMaxPerRoute(POOL_MAX_PEER_ROUTE);
// 将指定的目标主机的最大连接数增加到50
// HttpHost hostxxx = new HttpHost("http://xxxx.com",80);
// connManager.setMaxPerRoute(new HttpRoute(hostxxx), 50);
// 初始化http客户端
client = HttpClients.custom().setConnectionManager(connManager).build();
logger.info("Init HTTP Client");
} catch (Exception e) {
logger.error("http工具初始化出错", e);
}
}
/**
*
* <p>Discription:[构建公用RequestConfig]</p>
* @return
* @author bx_zhengyingjun 2021-1-20
* @update [修改人] [修改时间] [变更描述]
*/
public static RequestConfig buildRequestConfig() {
// 设置请求和传输超时时间
RequestConfig requestConfig = RequestConfig.custom()
.setSocketTimeout(SO_TIMEOUT_MS)
.setConnectTimeout(CONNECTION_TIMEOUT_MS).build();
return requestConfig;
}
/**
*
* <p>Discription:[以HTTP方式POST发送byte数组]</p>
* @param url 地址
* @param params 文件
* @param headers 特殊请求头
* @return
* @throws Exception
* @author zhengyingjun 2021-1-20
* @update [修改人] [修改时间] [变更描述]
*/
public static byte[] POST_BYTES(String url, byte[] params,Map<String,String> headers) throws Exception {
return bytesPostInvoke(url, params,headers);
}
/**
*
* <p>Discription:[以HTTP方式GET请求byte数组]</p>
* @param url
* @param parms
* @param headers
* @return
* @throws Exception
* @author zhengyingjun 2021-1-21
* @update [修改人] [修改时间] [变更描述]
*/
public static byte[] GET_WITHHEADERS(String url,Map<String,String> parms,Map<String,String> headers) throws Exception{
return bytesGetInvoke(url,parms,headers);
}
/**
*
* <p>Discription:[使用GET请求,返回byte[]]</p>
* @param url
* @param params
* @param headers
* @return
* @throws Exception
* @author zhengyingjun 2021-1-21
* @update [修改人] [修改时间] [变更描述]
*/
public static byte[] bytesGetInvoke(String url,Map<String,String> params,Map<String,String> headers) throws Exception {
CloseableHttpResponse response = null;
HttpGet get = buildHttpGet(url,params,headers);
try {
response = client.execute(get);
logger.info("返回状态码:"+response.getStatusLine().getStatusCode());
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
HttpEntity entity = response.getEntity();
if (entity != null) {
// 输入流关闭,同时会自动触发http连接的release
return EntityUtils.toByteArray(entity);
}
}else {
System.out.println(response.getStatusLine().getStatusCode());
get.abort();
}
} catch (Exception e) {
e.printStackTrace();
throw new Exception(e);
}finally{
HttpClientUtils.closeQuietly(response);
get.releaseConnection();
}
return null;
}
/**
*
* <p>Discription:[使用POST请求,返回byte[]]</p>
* @param url
* @param params
* @return
* @throws Exception
* @author zhengyingjun 2021-1-20
* @update [修改人] [修改时间] [变更描述]
*/
public static byte[] bytesPostInvoke(String url,byte[] params,Map<String,String> headers) throws Exception {
CloseableHttpResponse response = null;
HttpPost post = buildBytesHttpPost(url, params,headers);
try {
response = client.execute(post);
logger.info("返回状态码:"+response.getStatusLine().getStatusCode());
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
HttpEntity entity = response.getEntity();
if (entity != null) {
// 输入流关闭,同时会自动触发http连接的release
return EntityUtils.toByteArray(entity);
}
}else {
post.abort();
}
} catch (Exception e) {
e.printStackTrace();
throw new Exception(e);
}finally{
HttpClientUtils.closeQuietly(response);
post.releaseConnection();
}
return null;
}
/**
*
* <p>Discription:[构建httpPost对象]</p>
* @param url
* @param params
* @return
* @throws Exception
* @author zhengyingjun 2021-1-21
* @update [修改人] [修改时间] [变更描述]
*/
public static HttpPost buildBytesHttpPost(String url, byte[] params,Map<String,String> headers) throws Exception {
HttpPost post = new HttpPost(url);
setHttpFormHeaderPost(post,headers);
// 设置超时时间
post.setConfig(buildRequestConfig());
// 非空判断
if(null != params){
ByteArrayEntity bae = new ByteArrayEntity(params);
bae.setContentType(CONTENT_TYPE_OCTET_STREAM);
post.setEntity(bae);
}
return post;
}
/**
*
* <p>Discription:构建httpGet对象</p>
* @param url 地址
* @param params 请求参数
* @param otherHeaders 请求头
* @return
* @throws URISyntaxException
* @author zhengyingjun 2021-1-20
* @update [修改人] [修改时间] [变更描述]
*/
public static HttpGet buildHttpGet(String url, Map<String, String> params,Map<String,String> otherHeaders)throws URISyntaxException {
HttpGet get = new HttpGet(buildGetUrl(url, params));
setHttpFormHeaderGet(get,otherHeaders);
// 设置超时时间
get.setConfig(buildRequestConfig());
return get;
}
/**
*
* <p>Discription:[设置HttpMethod form表单提交方式头]</p>
* @param httpMethod
* @author zhengyingjun 2021-1-20
* @update [修改人] [修改时间] [变更描述]
*/
public static void setHttpFormHeaderPost(HttpRequestBase httpMethod,Map<String,String> otherHeaders) {
// 设置内容编码格式
httpMethod.setHeader(HTTP.CONTENT_ENCODING, CONTENT_CHARSET);
// 设置头部数据类型及编码
httpMethod.setHeader(HTTP.CONTENT_TYPE, CONTENT_TYPE_FORM);
//测试数据 start
// httpMethod.setHeader("Host","gz.bcebos.com");
// httpMethod.setHeader("x-bce-date","2021-01-21T02:31:56Z");
// httpMethod.setHeader("Authorization","bce-auth-v1/48b91e0481e84d42811e15a216335814/2021-01-21T02:32:48Z/1800/host;x-bce-date/fe2cd9c988ae20371eb2723c453e7d730d1a6d50e1c127172cdfea344278c0b5");
//测试数据 end
if(null != otherHeaders){
for (String key : otherHeaders.keySet()) {
httpMethod.setHeader(key,otherHeaders.get(key));
}
}
}
/**
*
* <p>Discription:[设置get header]</p>
* @param httpMethod
* @author zhengyingjun 2021-1-20
* @update [修改人] [修改时间] [变更描述]
*/
public static void setHttpFormHeaderGet(HttpRequestBase httpMethod,Map<String,String> otherHeaders) {
if(null != otherHeaders){
for (String key : otherHeaders.keySet()) {
httpMethod.setHeader(key,otherHeaders.get(key));
}
}
}
/**
*
* <p>Discription:构造Get请求 url</p>
* @param url
* @param params
* @return
* @author zhengyingjun 2021-1-20
* @update [修改人] [修改时间] [变更描述]
*/
private static String buildGetUrl(String url, Map<String, String> params) {
StringBuffer uriStr = new StringBuffer(url);
if (params != null) {
List<NameValuePair> ps = new ArrayList<NameValuePair>();
for (String key : params.keySet()) {
ps.add(new BasicNameValuePair(key, params.get(key)));
}
uriStr.append("?");
uriStr.append(URLEncodedUtils.format(ps, UTF_8));
}
return uriStr.toString();
}
}
百度IAM签名工具
package com.cccp.common.baidubos;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import com.google.common.base.Joiner;
import org.apache.commons.codec.binary.Hex;
/**
*
* <p>Title: [百度IAM签名工具] </p>
* <p>Description: [生成认证字符串 authorization]</p>
* @author zhengyingjun
* @update [修改人] [修改时间]
* @version v1.0
*/
public class IAMUtil {
/**
* 1、创建前缀字符串(authStringPrefix)。
* 2、创建规范请求(canonicalRequest),即待签名字符串,在此过程中可同时确定签名头域(signedHeaders)。
* 3、使用您的智能云秘密访问密钥(SK)与前缀字符串(authStringPrefix),通过HMAC算法计算出派生签名密钥(signingKey)。
* 4、使用派生签名密钥对规范请求进行签名计算,得到最终的签名摘要。
* 5、将前缀字符串和上一步生成的签名摘要拼接为认证字符串,并添加到API请求的标头(Header)中或者添加到查询字符串参数。
* 百度智能云服务收到请求后,将按照上述相同步骤来计算请求中发送的签名。然后对计算得到的签名与您在请求中发送的签名进行比较。如果签名匹配,则继续处理请求,如果签名不匹配,则拒绝请求,并报错。
*/
private static final Joiner headerJoiner = Joiner.on('\n');
/**
*
* <p>Discription:构造认证字符串机构</p>
* @param accessKeyId
* @param secretAccessKey
* @return
* @author zhengyingjun 2021-1-18
* @throws Exception
* @update [修改人] [修改时间] [变更描述]
*/
public String createAuthorization(Map<String,String> map,SortedMap<String, String> headers) throws Exception{
String authorization = "";
//1、创建前缀字符串(authStringPrefix):bce-auth-v1/{accessKeyId}/{timestamp}/{expirationPeriodInSeconds}
String authStringPrefix = map.get("bce-auth")+"/"+map.get("accessKeyId")+"/"+map.get("timestamp")+"/"+map.get("expirationPeriodInSeconds");
//2、创建规范请求(canonicalRequest),确定签名头域(signedHeaders)
//生成CanonicalURI
String canonicalURI = map.get("uri");
//生成CanonicalQueryString
String canonicalQueryString = "";//查询条件默认为空
//生成CanonicalHeaders
String canonicalHeaders = dealWithCanonicalHeaders(headers);
String canonicalRequest = map.get("method")+"\n"+canonicalURI+"\n"+canonicalQueryString+"\n"+canonicalHeaders;
//3、生成signingKey
String signingKey = sha256Hex(map.get("SecretAccessKey"),authStringPrefix);
//4、生成Signature
String signature = sha256Hex(signingKey,canonicalRequest);
//5、待签名signedHeaders
String signedHeaders = "host;x-bce-date";//无变化不需改动
//6、返回Authorization
authorization = authStringPrefix + "/" + signedHeaders + "/" + signature;
return authorization;
}
/**
*
* <p>Discription:处理不包含authorization的请求头</p>
* @param headers
* @return
* @author zhengyingjun 2021-1-19
* @update [修改人] [修改时间] [变更描述]
*/
private String dealWithCanonicalHeaders(SortedMap<String, String> headers){
if (headers.isEmpty()) {
return "";
}
List<String> headerStrings = new ArrayList<String>();
for (Map.Entry<String, String> entry : headers.entrySet()) {
String key = entry.getKey();
if (key == null) {
continue;
}
String value = entry.getValue();
if (value == null) {
value = "";
}
headerStrings.add(key + ':' + value);
}
Collections.sort(headerStrings);
return headerJoiner.join(headerStrings);
}
/**
*
* <p>Discription:sha256Hex处理</p>
* @param signingKey
* @param stringToSign
* @return
* @author zhengyingjun 2021-1-21
* @update [修改人] [修改时间] [变更描述]
*/
private String sha256Hex(String signingKey, String stringToSign) {
try {
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(signingKey.getBytes(Charset.forName("UTF8")), "HmacSHA256"));
return new String(Hex.encodeHex(mac.doFinal(stringToSign.getBytes(Charset.forName("UTF8")))));
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
baidu_bos.properties配置文件内容
accesskeyid=xxxxxxxxxxxxxxxxxxxxx
secretaccesskey=xxxx
host=gz.bcebos.com
bos_start=true
本文参考:
百度智能云文档-Java SDK
https://cloud.baidu.com/doc/BOS/s/Ojwvyrpgd#配置https协议访问bos
Самое ценное, что есть жизнь. Жизнь принадлежит нам только один раз. Жизнь человека должна проводиться таким образом: Когда он смотрит назад, он не из-за безделье угрызений совести, ни стыда за прошлое, что жить - так В его смерти, можно сказать: вся моя жизнь и энергии была посвящена самым великолепным карьеру в мире - за свободу и освободительной борьбы

浙公网安备 33010602011771号