转载请表明出处 https://blog.csdn.net/Amor_Leo/article/details/106843750 谢谢
<!-- oss 阿里储存-->
com.aliyun.oss
aliyun-sdk-oss
3.8.1
# OSS相关配置信息
aliyun:
oss:
endpoint: xxxx # oss对外服务的访问域名
accessKeyId: xxxx # 访问身份验证中用到用户标识
accessKeySecret: xxxx # 用户用于加密签名字符串和oss用来验证签名字符串的密钥
bucketName: xxxx# oss的存储空间
baseFile: zzz/ #指定上传文件夹
urlPrefix: http://oss的存储空间.oss对外服务的访问域名/
oss分片上传
/**
* 阿里OSS对象存储文件上传工具类
*
* @author LHL
*/
@Slf4j
@Component
public class FileUploadOssUtil {
private static String endpoint;
private static String accessKeyId;
private static String accessKeySecret;
private static String bucketName;
private static String baseFile;
private static String urlPrefix;
@Value("${aliyun.oss.endpoint}")
public void setEndpoint(String endpoint) {
this.endpoint = endpoint;
}
@Value("${aliyun.oss.accessKeyId}")
public void setAccessKeyId(String accessKeyId) {
this.accessKeyId = accessKeyId;
}
@Value("${aliyun.oss.accessKeySecret}")
public void setAccessKeySecret(String accessKeySecret) {
this.accessKeySecret = accessKeySecret;
}
@Value("${aliyun.oss.bucketName}")
public void setBucketName(String bucketName) {
this.bucketName = bucketName;
}
@Value("${aliyun.oss.baseFile}")
public void setBaseFile(String baseFile) {
this.baseFile = baseFile;
}
@Value("${aliyun.oss.urlPrefix}")
public void setUrlPrefix(String urlPrefix) {
this.urlPrefix = urlPrefix;
}
private static String key = null;
private static OSS client = null;
/**
* 定长线程池
*/
private static ExecutorService threadPool;
private static List<PartETag> partETags = null;
/**
* 2MB 分片大小
*/
private static final int partSize = 2 * 1024 * 1024;
private static int counter = 0;
/**
* 删除文件
*/
public static boolean remove(String filePath) {
String path = filePath.replaceAll(urlPrefix, "");
try {
client = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
client.deleteObject(bucketName, path);
log.info("oss删除成功 路径: {}", filePath);
} catch (OSSException e) {
log.error(e.getMessage(), e);
return false;
} finally {
if (client != null) {
client.shutdown();
}
}
return true;
}
/*
* 上传oss
* @author LHL
*/
private static String upload(MultipartFile multipartFile, String baseDir) throws IOException {
String fileName = multipartFile.getOriginalFilename();
long start = System.currentTimeMillis();
String[] names = fileName.split("\\.");
String fileTypeName = names[names.length - 1];
key = baseDir + "/" + UUID.randomUUID().toString().replaceAll("-", "") + "." + fileTypeName;
client = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
String fileUrl = null;
try {
String uploadId = claimUploadId(key);
log.info("申请一个新的上传id:" + uploadId);
// 文件大小
long fileLength = multipartFile.getSize();
// 分片总数(总共分几个部分)
int partCount = (int) (fileLength / partSize);
if (fileLength % partSize != 0) {
partCount++;
}
if (partCount > 10000) {
log.warn("partCount总数不应超过10000");
return null;
} else {
log.info("文件总共分片数:" + partCount);
}
partETags = Collections.synchronizedList(new ArrayList<PartETag>(partCount));
CountDownLatch latch = new CountDownLatch(partCount);
log.info("***************开始准备上传************");
threadPool = ThreadConstants.getMyThreadPool();
for (int i = 0; i < partCount; i++) {
long startPos = i * partSize;
long curPartSize = (i + 1 == partCount) ? (fileLength - startPos) : partSize;
threadPool.execute(new PartUploader(multipartFile, startPos, curPartSize, i + 1, uploadId, latch));
}
latch.await();
if (partETags.size() != partCount) {
StringBuilder partETagsStr = new StringBuilder("(");
for (PartETag item : partETags) {
partETagsStr.append(item.getPartNumber()).append(",");
}
partETagsStr.append(")");
log.info(String.format("partCount:%s*******,partEtages:%s*******,partETagsSize:%s", partCount, partETagsStr, partETags.size()));
throw new IllegalStateException("上传多个部分失败,因为有些部分还没有完成");
} else {
log.info("成功地将多个部分合并上传到一个名为的对象中 " + key);
}
listAllParts(uploadId);
completeMultipartUpload(uploadId);
log.info("获取一个对象");
long end = System.currentTimeMillis();
// 生成文件地址
boolean isFileExist = client.doesObjectExist(bucketName, key);
if (isFileExist) {
fileUrl = urlPrefix + key;
log.info(String.format("上传成功*****耗时:%s*****,文件地址:%s", ((end - start) / 1000), fileUrl));
} else {
throw new Exception("上传失败,文件不存在");
}
} catch (OSSException oe) {
log.error(oe.getMessage(), oe);
} catch (ClientException ce) {
log.error(ce.getErrorMessage(), ce);
} catch (Exception e) {
log.error(e.getMessage(), e);
} finally {
if (client != null) {
client.shutdown();
}
partETags.clear();
partETags = null;
}
return fileUrl;
}
/**
* 静态内部类,上传组件
*/
private static class PartUploader implements Runnable {
private MultipartFile localFile;
private long partSize;
private int partNumber;
private String uploadId;
private long startPos;
private CountDownLatch latch;
public PartUploader(MultipartFile localFile, long startPos, long partSize, int partNumber, String uploadId, CountDownLatch latch) {
this.localFile = localFile;
this.partSize = partSize;
this.partNumber = partNumber;
this.uploadId = uploadId;
this.startPos = startPos;
this.latch = latch;
}
@Override
public void run() {
InputStream instream = null;
try {
log.info("Part#" + this.partNumber + " 开始上传\n");
instream = localFile.getInputStream();
instream.skip(startPos);
UploadPartRequest uploadPartRequest = new UploadPartRequest();
uploadPartRequest.setBucketName(bucketName);
uploadPartRequest.setKey(key);
uploadPartRequest.setUploadId(this.uploadId);
uploadPartRequest.setInputStream(instream);
uploadPartRequest.setPartSize(this.partSize);
uploadPartRequest.setPartNumber(this.partNumber);
UploadPartResult uploadPartResult = client.uploadPart(uploadPartRequest);
log.info("Part#" + this.partNumber + " 完毕\n");
synchronized (partETags) {
partETags.add(uploadPartResult.getPartETag());
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (instream != null) {
try {
instream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
latch.countDown();
}
}
}
private static String claimUploadId(String path) {
InitiateMultipartUploadRequest request = new InitiateMultipartUploadRequest(bucketName, key);
// 大家可根据自己的文件类型,设置不同的响应content-type
String contentType = getContentType(path);
if (StringUtils.isNotBlank(contentType)) {
request.addHeader("Content-Type", contentType);
}
request.addHeader("Cache-Control", "no-cache");
InitiateMultipartUploadResult result = client.initiateMultipartUpload(request);
return result.getUploadId();
}
//有些不常用的可能有问题
private static String getContentType(String inputPath) {
String type = inputPath.substring(inputPath.lastIndexOf(".") + 1).toLowerCase();
// 判断是否为音频 mp3、aac、ape/flac、wav、wma、amr、mid
if (type.equalsIgnoreCase("mp3")) {
return "audio/mpeg";
} else if (type.equalsIgnoreCase("aac")) {
return "audio/mpeg";
} else if (type.equalsIgnoreCase("ape")) {
return "audio/mpeg";
} else if (type.equalsIgnoreCase("wav")) {
return "audio/mpeg";
} else if (type.equalsIgnoreCase("wma")) {
return "audio/mpeg";
} else if (type.equalsIgnoreCase("amr")) {
return "audio/AMR";
} else if (type.equalsIgnoreCase("mid")) {
return "audio/mpeg";
}
//判断是否为图片 jpg、png、gif、bmp、ico、tif(tiff)、psd/psb、WebP、RAW、pdf、DCM、sai/rif
else if (type.equalsIgnoreCase("jpg")) {
return "image/jpg";
} else if (type.equalsIgnoreCase("jpeg")) {
return "image/jpg";
} else if (type.equalsIgnoreCase("png")) {
return "image/jpg";
} else if (type.equalsIgnoreCase("gif")) {
return "image/gif";
} else if (type.equalsIgnoreCase("tif")) {
return "image/tiff";
} else if (type.equalsIgnoreCase("tiff")) {
return "image/tiff";
} else if (type.equalsIgnoreCase("bmp")) {
return "image/bmp";
} else if (type.equalsIgnoreCase("pdf")) {
return "application/pdf";
} else if (type.equalsIgnoreCase("psd")) {
return "application/vnd.ms-xpsdocument";
} else if (type.equalsIgnoreCase("psb")) {
return "image/jpeg";
}
//判断是否为视频 mp4/m4v/3gp/mpg、flv/f4v/swf、avi、wmv、rmvb、mov、mts/m2t、webm/ogg/mkv
else if (type.equalsIgnoreCase("mp4")) {
return "video/mp4";
} else if (type.equalsIgnoreCase("avi")) {
return "video/avi";
} else if (type.equalsIgnoreCase("mov")) {
return "video/mp4";
} else if (type.equalsIgnoreCase("flv")) {
return "video/mp4";
} else if (type.equalsIgnoreCase("wmv")) {
return "video/mp4";
} else if (type.equalsIgnoreCase("asf")) {
return "allpication/vnd.ms-asf";
} else if (type.equalsIgnoreCase("asx")) {
return "allpication/vnd.ms-asf";
} else if (type.equalsIgnoreCase("wmv9")) {
return "video/x-ms-wmv";
} else if (type.equalsIgnoreCase("3gp")) {
return "audio/3gpp";
} else if (type.equalsIgnoreCase("mpg")) {
return "video/mpeg";
} else if (type.equalsIgnoreCase("rm")) {
return "video/mp4";
} else if (type.equalsIgnoreCase("rmvb")) {
return "video/mp4";
} else if (type.equalsIgnoreCase("mts")) {
return "model/vnd.mts";
} else if (type.equalsIgnoreCase("m2t")) {
return "video/mp4";
} else if (type.equalsIgnoreCase("ogg")) {
return "application/ogg";
} else if (type.equalsIgnoreCase("m4v")) {
return "video/mp4";
} else if (type.equalsIgnoreCase("mkv")) {
return "video/mp4";
} else if (type.equalsIgnoreCase("f4v")) {
return "video/mp4";
} else if (type.equalsIgnoreCase("swf")) {
return "video/vnd.sealed.swf";
} else if (type.equalsIgnoreCase("webm")) {
return "video/mp4";
}
return null;
}
private static void completeMultipartUpload(String uploadId) {
// Make part numbers in ascending order
Collections.sort(partETags, new Comparator<PartETag>() {
@Override
public int compare(PartETag p1, PartETag p2) {
return p1.getPartNumber() - p2.getPartNumber();
}
});
log.info("Completing to upload multiparts\n");
CompleteMultipartUploadRequest completeMultipartUploadRequest =
new CompleteMultipartUploadRequest(bucketName, key, uploadId, partETags);
client.completeMultipartUpload(completeMultipartUploadRequest);
}
private static void listAllParts(String uploadId) {
log.info("Listing all parts......");
ListPartsRequest listPartsRequest = new ListPartsRequest(bucketName, key, uploadId);
PartListing partListing = client.listParts(listPartsRequest);
int partCount = partListing.getParts().size();
for (int i = 0; i < partCount; i++) {
PartSummary partSummary = partListing.getParts().get(i);
log.info("\tPart#" + partSummary.getPartNumber() + ", ETag=" + partSummary.getETag());
}
}
/**
* 上传执行器
*/
public synchronized static String fileUpload(MultipartFile multipartFile) {
ReentrantLock lock = new ReentrantLock();
lock.lock();
long start = System.currentTimeMillis();
String fileName = multipartFile.getOriginalFilename();
String baseDir = checkContentType(fileName);
try {
baseDir = baseFile + baseDir + "/" + DateUtil.parseDateToStr("yyyyMM", new Date());
String fileUrl = upload(multipartFile, baseDir);
long end = System.currentTimeMillis();
log.info("文件上传结束,共耗时" + (end - start) + "ms");
return fileUrl;
} catch (IOException e) {
e.printStackTrace();
return null;
} finally {
lock.unlock();
}
}
private static final File getAbsoluteFile(String filename) throws IOException {
File desc = new File(File.separator + filename);
if (!desc.getParentFile().exists()) {
desc.getParentFile().mkdirs();
}
if (!desc.exists()) {
desc.createNewFile();
}
return desc;
}
private static final String encodingFilename(String filename, String extension) {
filename = filename.replace("_", " ");
filename = MD5Util.md5Encrypt32Lower(filename + System.nanoTime() + counter++) + extension;
return filename;
}
public static String checkContentType(String inputPath) {
String type = inputPath.substring(inputPath.lastIndexOf(".") + 1).toLowerCase();
// 判断是否为音频 mp3、aac、ape/flac、wav、wma、amr、mid
if (type.equalsIgnoreCase("mp3")) {
return "audio";
} else if (type.equalsIgnoreCase("aac")) {
return "audio";
} else if (type.equalsIgnoreCase("ape")) {
return "audio";
} else if (type.equalsIgnoreCase("wav")) {
return "audio";
} else if (type.equalsIgnoreCase("wma")) {
return "audio";
} else if (type.equalsIgnoreCase("amr")) {
return "audio";
} else if (type.equalsIgnoreCase("mid")) {
return "audio";
}
//判断是否为图片 jpg、png、gif、bmp、ico、tif(tiff)、psd/psb、WebP、RAW、pdf、DCM、sai/rif
else if (type.equalsIgnoreCase("jpg")) {
return "picture";
} else if (type.equalsIgnoreCase("jpeg")) {
return "picture";
} else if (type.equalsIgnoreCase("png")) {
return "picture";
} else if (type.equalsIgnoreCase("gif")) {
return "picture";
} else if (type.equalsIgnoreCase("tif")) {
return "picture";
} else if (type.equalsIgnoreCase("tiff")) {
return "picture";
} else if (type.equalsIgnoreCase("bmp")) {
return "picture";
} else if (type.equalsIgnoreCase("pdf")) {
return "picture";
} else if (type.equalsIgnoreCase("psd")) {
return "picture";
} else if (type.equalsIgnoreCase("psb")) {
return "picture";
}
//判断是否为视频 mp4/m4v/3gp/mpg、flv/f4v/swf、avi、wmv、rmvb、mov、mts/m2t、webm/ogg/mkv
else if (type.equalsIgnoreCase("mp4")) {
return "video";
} else if (type.equalsIgnoreCase("avi")) {
return "video";
} else if (type.equalsIgnoreCase("mov")) {
return "video";
} else if (type.equalsIgnoreCase("flv")) {
return "video";
} else if (type.equalsIgnoreCase("wmv")) {
return "video";
} else if (type.equalsIgnoreCase("asf")) {
return "video";
} else if (type.equalsIgnoreCase("asx")) {
return "video";
} else if (type.equalsIgnoreCase("wmv9")) {
return "video";
} else if (type.equalsIgnoreCase("3gp")) {
return "video";
} else if (type.equalsIgnoreCase("mpg")) {
return "video";
} else if (type.equalsIgnoreCase("rm")) {
return "video";
} else if (type.equalsIgnoreCase("rmvb")) {
return "video";
} else if (type.equalsIgnoreCase("mts")) {
return "video";
} else if (type.equalsIgnoreCase("m2t")) {
return "video";
} else if (type.equalsIgnoreCase("ogg")) {
return "video";
} else if (type.equalsIgnoreCase("m4v")) {
return "video";
} else if (type.equalsIgnoreCase("mkv")) {
return "video";
} else if (type.equalsIgnoreCase("f4v")) {
return "video";
} else if (type.equalsIgnoreCase("swf")) {
return "video";
} else if (type.equalsIgnoreCase("webm")) {
return "video";
}
return "other";
}
}
/**
* 获取静态单例固定线程池
*
* @author LHL
*/
public class ThreadConstants {
public static final int MAX_THREAD_COUNT = 10;
/**
* 自定义线程池
*/
private static ExecutorService MY_THREAD_POOL;
/**
* 自定义线程池
*/
public static ExecutorService getMyThreadPool() {
if (MY_THREAD_POOL == null) {
MY_THREAD_POOL = Executors.newFixedThreadPool(MAX_THREAD_COUNT);
}
return MY_THREAD_POOL;
}
}