华为云OBS文件服务
准备工作
先获取OBS的SK,AK,终端节点。然后创建桶
将以上四个值存放在Nacos中
/**
* 取值为所创建的桶名
*/
@Value("${obs.bucketName}")
private String bucketName;
/**
* 取值为获取的AK
*/
@Value("${obs.accessKey}")
private String accessKey;
/**
* 取值为获取的SK
*/
@Value("${obs.secretKey}")
private String securityKey;
/**
* 取值为获取的终端节点
*/
@Value("${obs.endpoint}")
private String endpoint;
然后加入两个工具类
public class Signature {
public static String signWithHmacSha1(String sk, String canonicalString) throws UnsupportedEncodingException {
try {
SecretKeySpec signingKey = new SecretKeySpec(sk.getBytes("UTF-8"), "HmacSHA1");
Mac mac = Mac.getInstance("HmacSHA1");
mac.init(signingKey);
return Base64.getEncoder().encodeToString(mac.doFinal(canonicalString.getBytes("UTF-8")));
} catch (NoSuchAlgorithmException | InvalidKeyException | UnsupportedEncodingException e) {
e.printStackTrace();
}
return null;
}
}
public class DateUtils {
public static String formatDate(long time)
{
DateFormat serverDateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.ENGLISH);
serverDateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
return serverDateFormat.format(time);
}
}
OBS上传服务
当上传的文件名带有中文时,需要对文件名进行转码处理。否则会导致长度过长或者其他原因上传出错。
public Map<String, String> putObjectToBucket(MultipartFile file) {
// 获取文件名
String originalFilename = null;
try {
originalFilename = URLEncoder.encode(Objects.requireNonNull(file.getOriginalFilename()),"UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
// 处理文件名
String fileName = originalFilename != null ? originalFilename.substring(0, originalFilename.lastIndexOf(46)) + "_" + System.currentTimeMillis() + originalFilename.substring(originalFilename.lastIndexOf(46)) : null;
CloseableHttpClient httpClient = HttpClients.createDefault();
String requestTime = DateUtils.formatDate(System.currentTimeMillis());
HttpPut httpPut = new HttpPut(endpoint + "/" + fileName);
httpPut.addHeader("Date", requestTime);
//根据请求计算签名
String contentMD5 = "";
String contentType = "";
String canonicalizeHeaders = "";
String canonicalizeResource = "/" + bucketName + "/" + fileName;
// Content-MD5 、Content-Type 没有直接换行, data格式为RFC 1123,和请求中的时间一致
String canonicalString = "PUT" + "\n" + contentMD5 + "\n" + contentType + "\n" + requestTime + "\n" + canonicalizeHeaders + canonicalizeResource;
System.out.println("StringToSign:[" + canonicalString + "]");
try {
InputStream inputStream = file.getInputStream();
String signature = Signature.signWithHmacSha1(securityKey, canonicalString);
// 上传的文件
InputStreamEntity entity = new InputStreamEntity(inputStream);
httpPut.setEntity(entity);
// 增加签名头域 Authorization: OBS AccessKeyID:signature
httpPut.addHeader("Authorization", "OBS " + accessKey + ":" + signature);
CloseableHttpResponse httpResponse = httpClient.execute(httpPut);
// 打印发送请求信息
System.out.println("Request Message:");
System.out.println(httpPut.getRequestLine());
for (Header header : httpPut.getAllHeaders()) {
System.out.println(header.getName() + ":" + header.getValue());
}
System.out.println(httpResponse.getStatusLine().getStatusCode());
// 判断响应结果是否成功,此处返回文件在OBS中存储的路径及经过处理之后的文件名用来存入库
if (httpResponse.getStatusLine().getStatusCode() == 200) {
Map<String, String> map = new HashMap<>();
if (fileName != null){
map.put("fileName", URLDecoder.decode(fileName,"utf-8"));
map.put("path",endpoint + "/" + fileName);
return map;
}
return null;
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
httpClient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
OBS下载服务
下载主题类
此处还需要改进。下载的文件名如果是带有中文,文件名会乱码。目前测试过很多转码,解码方式。均未成功。
public void download(@RequestParam("fileId")String fileId, HttpServletRequest request, HttpServletResponse response) {
try {
CloseableHttpClient httpClient = HttpClients.createDefault();
SysFile sysFile = mapper.getPathAndFileName(fileId);
if (sysFile == null){
return;
}
String fileName = sysFile.getFileName();
HttpResponse httpResponse = utils.fileDownload(httpClient, sysFile);
InputStream inputStream = httpResponse.getEntity().getContent();
// 缓冲文件输出流
BufferedOutputStream outputStream = new BufferedOutputStream(response.getOutputStream());
// 为防止 文件名出现乱码
final String userAgent = request.getHeader("USER-AGENT");
// IE浏览器
if (StringUtils.contains(userAgent, "MSIE")) {
fileName = URLEncoder.encode(fileName, "UTF-8");
} else {
// google,火狐浏览器
if (StringUtils.contains(userAgent, "Mozilla")) {
fileName = new String(fileName.getBytes(), "ISO8859-1");
} else {
// 其他浏览器
fileName = URLEncoder.encode(fileName, "UTF-8");
}
}
response.setContentType("application/x-download");
// 设置让浏览器弹出下载提示框,而不是直接在浏览器中打开
response.addHeader("Content-Disposition", "attachment;filename=" + fileName);
IOUtils.copy(inputStream, outputStream);
outputStream.flush();
inputStream.close();
outputStream.close();
try {
httpClient.close();
} catch (IOException e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
}
下载工具类
下载其实就是将上传到额httpPut请求改成httpGet
/**
* 从obs下载文件
* @param httpClient 连接
* @param sysFile 文件实体
* @return 文件流
*/
public CloseableHttpResponse fileDownload(CloseableHttpClient httpClient,SysFile sysFile) {
String requestTime = DateUtils.formatDate(System.currentTimeMillis());
HttpGet httpGet = new HttpGet(sysFile.getPath());
httpGet.addHeader("Date", requestTime);
// 根据请求计算签名
String contentMD5 = "";
String contentType = "";
String canonicalizeHeaders = "";
String canonicalizeResource = null;
try {
canonicalizeResource = "/" + bucketName + "/" + URLEncoder.encode(sysFile.getFileName(),"UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
// Content-MD5 、Content-Type 没有直接换行, data格式为RFC 1123,和请求中的时间一致
String canonicalString = "GET" + "\n" + contentMD5 + "\n" + contentType + "\n" + requestTime + "\n" + canonicalizeHeaders + canonicalizeResource;
System.out.println("StringToSign:[" + canonicalString + "]");
try {
String signature = Signature.signWithHmacSha1(securityKey, canonicalString);
httpGet.setHeader("Authorization", "OBS " + accessKey + ":" + signature);
CloseableHttpResponse httpResponse = httpClient.execute(httpGet);
// 打印发送请求信息和收到的响应消息
System.out.println("Request Message:");
System.out.println(httpGet.getRequestLine());
for (Header header : httpGet.getAllHeaders()) {
System.out.println(header.getName() + ":" + header.getValue());
}
System.out.println("Response Message:");
System.out.println(httpResponse.getStatusLine());
for (Header header : httpResponse.getAllHeaders()) {
System.out.println(header.getName() + ":" + header.getValue());
}
return httpResponse;
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
}
return null;
}