阿里云OSS没有直接上传目录的API,恰巧项目需要,就写了个比较完备的API,可直接copy当做spring bean用,每次都从头写太麻烦,还是记录下来用吧。
package com.shinewonder.ad.springcomponent;
import java.io.File;
import java.io.InputStream;
import java.net.URL;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import com.aliyun.oss.ClientException;
import com.aliyun.oss.HttpMethod;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.common.auth.Credentials;
import com.aliyun.oss.common.comm.ResponseMessage;
import com.aliyun.oss.common.comm.SignVersion;
import com.aliyun.oss.model.*;
import com.aliyun.oss.model.SetBucketCORSRequest.CORSRule;
/**
* @comment 阿里云OSS工具类,直接@Autowired,然后使用即可
*/
@Component
public class GlobalALiYunOSSUtil implements OSS {
private Logger logger = LoggerFactory.getLogger(getClass().getTypeName());
@Value("#{learncfg['aliOSS.endpoint']}")
private String endpoint;
@Value("#{learncfg['aliOSS.accessKeyId']}")
private String accessKeyId;
@Value("#{learncfg['aliOSS.accessKeySecret']}")
private String accessKeySecret;
@Value("#{learncfg['aliOSS.file.rootdir']}")
private String OSSFileRootdir;
private OSS ossClient;
@PostConstruct
private void initMethod() {
ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
}
@PreDestroy
private void destroyMethod() {
ossClient.shutdown();
}
/**
* 向OSS上传目录及其所包含的所有文件
* 例:目录/A/B/C下有文件1.txt,则最终css存储的kay为prefixPath/C/1.txt,即prefixPath+目录名+目录下文件相对路径
* @param bucketName
* @param prefixPath
* @param rootDir 必须是绝对路径
* @param checkFileExist true:检测文件是否已在OSS存在,文件不存在则上传到OSS,文件存在则不再上传到OSS,false:不检测文件是否已在OSS存在,直接上传到OSS
* @param infoMap 可传入一个ConcurrentHashMap,putDirectory会以infoKey为map的key,把当前进行中的OSS的key放在infoMap中,外界则可以通过infoMap.get(infoKey)拿到当前正在往OSS上传的文件的key
* @param infoKey map的key,可自定义,绝不能重复,否则会导致拿到的信息错乱,infoMap或infoKey只要有一个为null,则外界不可通过infoMap拿到正在进行中OSS的key
* @return true 上传成功
*/
public boolean putDirectory(final String bucketName, final String prefixPath, final File rootDir, final boolean checkFileExist, final ConcurrentHashMap<String, String> infoMap,
final String infoKey) {
boolean r = true;
if (!(rootDir.isDirectory() && rootDir.isAbsolute())) {
//检测根目录合法性
throw new IllegalArgumentException("root dir must exist and is absolute.");
}
ConcurrentLinkedQueue<File> folders = new ConcurrentLinkedQueue<>(); //声明需要遍历的文件夹列表
folders.add(rootDir); //将根目录放入遍历列表
String key = "";
for (File file = folders.poll(); file != null; file = folders.poll()) {
//遍历文件夹遍历列表
File[] temFiles = file.listFiles();
for (File f : temFiles) {
if (f.isDirectory()) {
//是目录,放入文件夹遍历列表4
folders.add(f);
} else {
//是文件,上传到阿里OSS
key = "";
key += OSSFileRootdir + "/";
key += prefixPath + "/";
key += f.getAbsolutePath().substring(rootDir.getParent().length());
key = key.replaceAll("[\\\\/]+", "/");
if (infoMap != null && infoKey != null) {
infoMap.put(infoKey, key); //将当前进行中的key放入infoKey
}
if (checkFileExist) {
//首先检测文件是否已经在OSS上存在
boolean exist = false;
try {
exist = ossClient.doesObjectExist(bucketName, key);
} catch (Exception e) {
try {
exist = ossClient.doesObjectExist(bucketName, key);
} catch (Exception e1) {
try {
exist = ossClient.doesObjectExist(bucketName, key);
} catch (Exception e2) {
logger.warn("check file is exist on OSS fail:{}|{}|{}", bucketName, key, f.getAbsolutePath());
throw e2;
}
}
}
if (!exist) {
//若不在OSS上存在,则上传到OSS
try {
ossClient.putObject(bucketName, key, f);
} catch (Exception e) {
try {
ossClient.putObject(bucketName, key, f);
} catch (Exception e1) {
try {
ossClient.putObject(bucketName, key, f);
} catch (Exception e2) {
logger.warn("file not exist on OSS and upload fail:{}|{}|{}", bucketName, key, f.getAbsolutePath());
r = false;
break;
}
}
}
}
} else {
//不检查是否已在OSS存在,直接上传
try {
ossClient.putObject(bucketName, key, f);
} catch (Exception e) {
try {
ossClient.putObject(bucketName, key, f);
} catch (Exception e1) {
try {
ossClient.putObject(bucketName, key, f);
} catch (Exception e2) {
logger.warn("OSS upload fail:{}|{}|{}", bucketName, key, f.getAbsolutePath());
r = false;
break;
}
}
}
}
}
}
}
return r;
}
@Override
public void switchCredentials(Credentials creds) {
ossClient.switchCredentials(creds);
}
@Override
public void shutdown() {
/*
* do nothing, this method should make no effect.
*/
}
@Override
public Bucket createBucket(String bucketName) throws OSSException, ClientException {
return ossClient.createBucket(bucketName);
}
@Override
public Bucket createBucket(CreateBucketRequest createBucketRequest) throws OSSException, ClientException {
return ossClient.createBucket(createBucketRequest);
}
@Override
public void deleteBucket(String bucketName) throws OSSException, ClientException {
ossClient.deleteBucket(bucketName);
}
@Override
public void deleteBucket(GenericRequest genericRequest) throws OSSException, ClientException {
ossClient.deleteBucket(genericRequest);
}
@Override
public List<Bucket> listBuckets() throws OSSException, ClientException {
return ossClient.listBuckets();
}
@Override
public BucketList listBuckets(String prefix, String marker, Integer maxKeys) throws OSSException, ClientException {
return ossClient.listBuckets(prefix, marker, maxKeys);
}
@Override
public BucketList listBuckets(ListBucketsRequest listBucketsRe