首先我们要添加对应的依赖
<dependency>
<groupId>com.huaweicloud</groupId>
<artifactId>esdk-obs-java</artifactId>
<version>3.20.6.1</version>
</dependency>
不要忘记在启动类上添加
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
然后在对应的配置文件添加华为云对应的密钥,没有的话可以去华为云获取对应密钥
#obs
huawei:
obs:
ak: xxxxxxxxxxxx
sk: xxxxxxxxxxxxxx
upload:
endPoint: obs.xxxxxx.xxxxxx.com
bucketName: xxxxx
parentDir: xxx
然后我们创建对应的config类
package Hwei.OBS.demo.config;
import com.obs.services.ObsClient;
import com.obs.services.exception.ObsException;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
/**
* 华为obs配置类
*/
@Data
@Slf4j
@Configuration
public class HweiOBSConfig {
@Value("${huawei.obs.ak:home}")
private String accessKey;
@Value("${huawei.obs.sk:home}")
private String securityKey;
@Value("${huawei.obs.upload.endPoint:home}")
private String endPoint;
@Value("${huawei.obs.bucketName:home}")
private String bucketName;
/**
* 创建实例
* @return
*/
public ObsClient getInstance(){
return new ObsClient(accessKey,securityKey,endPoint);
}
/**
* 销毁实列
* @param obsClient
*/
public void destroy(ObsClient obsClient) {
try{
obsClient.close();
}catch (ObsException e){
log.error("obs执行失败",e);
}catch (Exception e){
log.error("执行失败",e);
}
}
}
这里我把需要的上传下载的方法封装起来了,这里获取到了文件上传的进度,如果前后台分离可以使用webSocket进行实时通讯,在这里就不详细讲了。
package Hwei.OBS.demo.util;
import Hwei.OBS.demo.config.HweiOBSConfig;
import Hwei.OBS.demo.dto.FileUploadStatus;
import com.obs.services.ObsClient;
import com.obs.services.exception.ObsException;
import com.obs.services.model.*;
import jdk.internal.util.xml.impl.Input;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
@Slf4j
@Configuration
public class HweiOBSUtil {
@Autowired
private HweiOBSConfig hweiOBSConfig;
/**
* 文件上传
* @param uploadFile 上传的文件
* @param FileName 文件名称
* @return 返回的路径
*/
public PutObjectResult fileUpload(MultipartFile uploadFile, String FileName){
ObsClient obsClient=null;
try {
//创建实例
obsClient = hweiOBSConfig.getInstance();
//获取文件信息
InputStream inputStream = uploadFile.getInputStream();
UploadFileRequest request1 = new UploadFileRequest(hweiOBSConfig.getBucketName(), FileName);
long available = inputStream.available();
PutObjectRequest request = new PutObjectRequest(hweiOBSConfig.getBucketName(), java.lang.String.valueOf(FileName), inputStream);
ObjectMetadata objectMetadata = new ObjectMetadata();
objectMetadata.setContentLength(available);
request.setMetadata(objectMetadata);
//设置公共读
request.setAcl(AccessControlList.REST_CANNED_PUBLIC_READ);
PutObjectResult putObjectResult = obsClient.putObject(request);
return putObjectResult;
} catch (IOException e) {
e.printStackTrace();
}finally {
//销毁实例
hweiOBSConfig.destroy(obsClient);
}
return null;
}
/**
* 获取文件上传进度
* @param fileName
* @return
*/
public FileUploadStatus getFileUploadPlan(String objectName){
ObsClient obsClient=null;
FileUploadStatus fileUploadStatus = new FileUploadStatus();
try {
obsClient=hweiOBSConfig.getInstance();
GetObjectRequest request = new GetObjectRequest(hweiOBSConfig.getBucketName(), objectName);
request.setProgressListener(new ProgressListener() {
@Override
public void progressChanged(ProgressStatus status) {
//上传的平均速度
fileUploadStatus.setAvgSpeed(status.getAverageSpeed());
//上传的百分比
fileUploadStatus.setPct(String.valueOf(status.getTransferPercentage()));
}
});
// 每下载1MB数据反馈下载进度
request.setProgressInterval(1024*1024L);
ObsObject obsObject = obsClient.getObject(request);
// 读取对象内容
InputStream input= obsObject.getObjectContent();
byte[] b = new byte[1024];
ByteArrayOutputStream byteArrayOutputStream= new ByteArrayOutputStream();
int len;
while ((len=input.read(b))!=-1 ){
//将每一次的数据写入缓冲区
byteArrayOutputStream.write(b,0,len);
}
byteArrayOutputStream.close();
input.close();
return fileUploadStatus;
}catch (Exception e){
e.printStackTrace();
}finally {
hweiOBSConfig.destroy(obsClient);
}
return null;
}
/**
* 文件下载
* @param request
* @param response
* @param fileName 文件名称
* @return
*/
public int fileDownload(HttpServletRequest request, HttpServletResponse response, String fileName){
try {
ObsClient obsClient = hweiOBSConfig.getInstance();
ObsObject obsObject = obsClient.getObject(hweiOBSConfig.getBucketName(), fileName);
InputStream input = obsObject.getObjectContent();
//缓冲文件输出流
BufferedOutputStream outputStream = new BufferedOutputStream(response.getOutputStream());
//设置让浏览器弹出下载提示框,而不是直接在浏览器中打开
response.addHeader("Content-Disposition", "attachment;filename=" + fileName);
IOUtils.copy(input,outputStream);
outputStream.flush();
outputStream.close();
input.close();
return 0;
}catch (Exception e){
log.error("文件下载失败:{}",e.getMessage());
return 1;
}
}
}
对应的Controller,这里在上传的时候去校验redis是否有上传成功的,如果有就直接返回对应的值,实现了秒传的效果。
package Hwei.OBS.demo.controller;
import Hwei.OBS.demo.config.WebSocketHandler;
import Hwei.OBS.demo.dto.FileUploadStatus;
import Hwei.OBS.demo.dto.R;
import Hwei.OBS.demo.dto.fileChunkDto;
import Hwei.OBS.demo.util.FileUtil;
import Hwei.OBS.demo.util.HweiOBSUtil;
import cn.hutool.crypto.SecureUtil;
import com.obs.services.model.PutObjectResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@RestController
@RequestMapping("huawei/obs")
public class ObsController {
@Autowired
private HweiOBSUtil hweiOBSUtil;
@Autowired
private WebSocketHandler webSocketHandler;
@Resource
private RedisTemplate redisTemplate;
/**
* 文件上传
* @param uploadFile
* @return
*/
@PostMapping("fileUpload")
public R fileUpload(MultipartFile uploadFile){
//讲文件转换为md5,实现唯一性
String fileString = FileUtil.MultipartFileToString(uploadFile);
String fileMd5 = SecureUtil.md5(fileString);
//reids是否存在
if (redisTemplate.hasKey(fileMd5)){
//存在返回名称
String fileUrl = (String) redisTemplate.opsForValue().get(fileMd5);
return R.ok().data(fileUrl);
}else{
//不存在上传并放入redis
PutObjectResult putObjectResult = hweiOBSUtil.fileUpload(uploadFile, uploadFile.getOriginalFilename());
if (putObjectResult!=null){
redisTemplate.opsForValue().set(fileMd5,putObjectResult.getObjectUrl());
return R.ok().data(putObjectResult.getObjectKey());
}else{
return R.error();
}
}
}
/**
* 查询上传进度
* @param fileName
*/
@GetMapping("realFilePlan")
public void redalFilePlan(String fileName) {
FileUploadStatus fileUploadPlan = hweiOBSUtil.getFileUploadPlan(fileName);
webSocketHandler.sendAllMessage(fileUploadPlan.getPct());
}
/**
* 下载文件
* @param request
* @param response
* @param fileName
* @return
*/
@GetMapping("fileDownload")
public R fileDownload(HttpServletRequest request, HttpServletResponse response, String fileName){
int i = hweiOBSUtil.fileDownload(request, response, fileName);
if(i==0){
return null;
}
return R.error();
}
}
对应的MultipartFile转成String
package Hwei.OBS.demo.util;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.multipart.MultipartFile;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
@Slf4j
@Configuration
public class FileUtil {
/**
* MultipartFile转成String
* @param file
* @return
*/
public static String MultipartFileToString(MultipartFile file){
InputStreamReader isr;
BufferedReader br;
StringBuilder txtResult = new StringBuilder();
try {
isr = new InputStreamReader(file.getInputStream(), StandardCharsets.UTF_8);
br = new BufferedReader(isr);
String lineTxt;
while ((lineTxt = br.readLine()) != null) {
txtResult.append(lineTxt);
}
isr.close();
br.close();
return txtResult.toString();
} catch (IOException e) {
e.printStackTrace();
return "";
}
}
}