文件存储服务
This commit is contained in:
parent
c22819d863
commit
45417dd0ec
|
|
@ -5,11 +5,6 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
/**
|
|
||||||
* 。
|
|
||||||
*
|
|
||||||
* @author jiang
|
|
||||||
*/
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@ConfigurationProperties(prefix = "obs")
|
@ConfigurationProperties(prefix = "obs")
|
||||||
public class ObsConfig {
|
public class ObsConfig {
|
||||||
|
|
|
||||||
|
|
@ -5,24 +5,19 @@ import com.bonus.common.core.utils.file.FileUtils;
|
||||||
import com.bonus.obs.config.ObsConfig;
|
import com.bonus.obs.config.ObsConfig;
|
||||||
import com.bonus.obs.domain.ObsInfo;
|
import com.bonus.obs.domain.ObsInfo;
|
||||||
import com.obs.services.ObsClient;
|
import com.obs.services.ObsClient;
|
||||||
import com.obs.services.model.DeleteObjectResult;
|
import com.obs.services.model.*;
|
||||||
import com.obs.services.model.GetObjectRequest;
|
|
||||||
import com.obs.services.model.ObsObject;
|
|
||||||
import com.obs.services.model.PutObjectResult;
|
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import javax.annotation.PostConstruct;
|
import javax.annotation.PostConstruct;
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.io.File;
|
import java.io.*;
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.net.URLConnection;
|
import java.net.URLConnection;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* @author bonus
|
||||||
*
|
|
||||||
* @author jiang
|
|
||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
public class ObsUtils {
|
public class ObsUtils {
|
||||||
|
|
@ -51,8 +46,91 @@ public class ObsUtils {
|
||||||
* @return 上传结果
|
* @return 上传结果
|
||||||
*/
|
*/
|
||||||
public ObsInfo uploadFile(String objectKey, File file) {
|
public ObsInfo uploadFile(String objectKey, File file) {
|
||||||
PutObjectResult putObjectResult = obsClient.putObject(obsConfig.getBucket(), objectKey, file);
|
if (file.length() < 100 * 1024 * 1024L) {
|
||||||
|
obsClient.putObject(obsConfig.getBucket(), objectKey, file);
|
||||||
return ObsInfo.builder().bucketName(obsConfig.getBucket()).name(FileUtils.getName(objectKey)).fileType(FileUtils.getName(objectKey).substring(FileUtils.getName(objectKey).lastIndexOf('.')).toLowerCase()).length(file.length()).path(objectKey).build();
|
return ObsInfo.builder().bucketName(obsConfig.getBucket()).name(FileUtils.getName(objectKey)).fileType(FileUtils.getName(objectKey).substring(FileUtils.getName(objectKey).lastIndexOf('.')).toLowerCase()).length(file.length()).path(objectKey).build();
|
||||||
|
} else {
|
||||||
|
return multipartUploadFile(objectKey, file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分段上传文件到OBS
|
||||||
|
*
|
||||||
|
* @param objectKey 文件在OBS中的键
|
||||||
|
* @param file 要上传的文件
|
||||||
|
* @return 上传结果
|
||||||
|
*/
|
||||||
|
public ObsInfo multipartUploadFile(String objectKey, File file) {
|
||||||
|
// 创建一个固定大小为10的线程池
|
||||||
|
ExecutorService executorService = Executors.newFixedThreadPool(10);
|
||||||
|
try {
|
||||||
|
InitiateMultipartUploadRequest initRequest = new InitiateMultipartUploadRequest(obsConfig.getBucket(), objectKey);
|
||||||
|
InitiateMultipartUploadResult initResult = obsClient.initiateMultipartUpload(initRequest);
|
||||||
|
String uploadId = initResult.getUploadId();
|
||||||
|
List<PartEtag> partETags = new ArrayList<>();
|
||||||
|
// 每个分段大小为5MB
|
||||||
|
long partSize = 5 * 1024 * 1024L;
|
||||||
|
long fileLength = file.length();
|
||||||
|
int partCount = (int) (fileLength / partSize);
|
||||||
|
if (fileLength % partSize != 0) {
|
||||||
|
partCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Future<UploadPartResult>> futures = new ArrayList<>();
|
||||||
|
|
||||||
|
for (int i = 0; i < partCount; i++) {
|
||||||
|
final int partNumber = i + 1;
|
||||||
|
final long offset = partSize * i;
|
||||||
|
final long size = Math.min(partSize, fileLength - offset);
|
||||||
|
Future<UploadPartResult> future = executorService.submit(() -> {
|
||||||
|
UploadPartRequest uploadPartRequest = new UploadPartRequest(
|
||||||
|
obsConfig.getBucket(),
|
||||||
|
objectKey,
|
||||||
|
size,
|
||||||
|
offset,
|
||||||
|
file
|
||||||
|
);
|
||||||
|
uploadPartRequest.setUploadId(uploadId);
|
||||||
|
uploadPartRequest.setPartNumber(partNumber);
|
||||||
|
|
||||||
|
return obsClient.uploadPart(uploadPartRequest);
|
||||||
|
});
|
||||||
|
futures.add(future);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Future<UploadPartResult> future : futures) {
|
||||||
|
UploadPartResult uploadPartResult = future.get();
|
||||||
|
partETags.add(new PartEtag(uploadPartResult.getEtag(), uploadPartResult.getPartNumber()));
|
||||||
|
}
|
||||||
|
|
||||||
|
executorService.shutdown();
|
||||||
|
executorService.awaitTermination(1, TimeUnit.HOURS);
|
||||||
|
|
||||||
|
// 完成分段上传
|
||||||
|
CompleteMultipartUploadRequest completeRequest = new CompleteMultipartUploadRequest(
|
||||||
|
obsConfig.getBucket(),
|
||||||
|
objectKey,
|
||||||
|
uploadId,
|
||||||
|
partETags
|
||||||
|
);
|
||||||
|
obsClient.completeMultipartUpload(completeRequest);
|
||||||
|
|
||||||
|
return ObsInfo.builder()
|
||||||
|
.bucketName(obsConfig.getBucket())
|
||||||
|
.name(FileUtils.getName(objectKey))
|
||||||
|
.fileType(FileUtils.getName(objectKey).substring(FileUtils.getName(objectKey).lastIndexOf('.')).toLowerCase())
|
||||||
|
.length(file.length())
|
||||||
|
.path(objectKey)
|
||||||
|
.build();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
} finally {
|
||||||
|
// 关闭线程池
|
||||||
|
executorService.shutdown();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -23,11 +23,7 @@ import java.io.UnsupportedEncodingException;
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
/**
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @author jiang
|
|
||||||
*/
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/oss")
|
@RequestMapping("/oss")
|
||||||
|
|
@ -72,8 +68,7 @@ public class OssController {
|
||||||
}
|
}
|
||||||
|
|
||||||
OSSObject ossObject = ossObjectR.getData();
|
OSSObject ossObject = ossObjectR.getData();
|
||||||
// 假设这个方法进行了恰当的文件名清理和验证
|
String safeFileName = FileUtils.getName(objectKey); // 假设这个方法进行了恰当的文件名清理和验证
|
||||||
String safeFileName = FileUtils.getName(objectKey);
|
|
||||||
if (!StringUtils.hasText(safeFileName)) {
|
if (!StringUtils.hasText(safeFileName)) {
|
||||||
response.setStatus(HttpStatus.BAD_REQUEST.value());
|
response.setStatus(HttpStatus.BAD_REQUEST.value());
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -57,9 +57,8 @@ public class OssUtils {
|
||||||
* @return 包含上传文件信息的结果对象
|
* @return 包含上传文件信息的结果对象
|
||||||
*/
|
*/
|
||||||
public R<OssInfo> upload(String objectKey, File file) {
|
public R<OssInfo> upload(String objectKey, File file) {
|
||||||
final long tenMegabytes = 10 * 1024 * 1024L;
|
|
||||||
try {
|
try {
|
||||||
if (file.length() < tenMegabytes) {
|
if (file.length() < 10 * 1024 * 1024L) {
|
||||||
ossClient.putObject(ossConfig.getBucket(), objectKey, file);
|
ossClient.putObject(ossConfig.getBucket(), objectKey, file);
|
||||||
} else {
|
} else {
|
||||||
ossMultipartParallelUpload(objectKey, file);
|
ossMultipartParallelUpload(objectKey, file);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue