java
复制代码
import cn.hutool.core.util.ZipUtil;
import com.amazonaws.ClientConfiguration;
import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.client.builder.AwsClientBuilder;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.*;
import com.crm.common.config.S3Config;
import com.crm.common.enums.ConflictPolicy;
import com.crm.common.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.LinkedList;
import java.util.List;
@Component
public class S3Utils {
private BasicAWSCredentials awsCreds = null;
private AmazonS3 s3 = null;
@Autowired
S3Config s3Config;
@PostConstruct
public void init() {
/**
* 创建s3对象
*/
if (StringUtils.isNotBlank(s3Config.getAccessKey()) && StringUtils.isNotBlank(s3Config.getSecretKey())) {
ClientConfiguration config = new ClientConfiguration();
AwsClientBuilder.EndpointConfiguration endpointConfig =
new AwsClientBuilder.EndpointConfiguration(s3Config.getEndpoint(), "cn-north-1");
awsCreds = new BasicAWSCredentials(s3Config.getAccessKey(), s3Config.getSecretKey());
s3 = AmazonS3ClientBuilder.standard()
.withEndpointConfiguration(endpointConfig)
.withClientConfiguration(config)
.withCredentials(new AWSStaticCredentialsProvider(awsCreds))
.build();
}
}
/**
* 上传文件
*
* @param file 文件
*/
public String uploadFile(MultipartFile file, String moduleName) {
return uploadFile(file, ConflictPolicy.NEW, moduleName);
}
/**
* @param file
* @param policy 冲突策略,当同一路径下有同名文件时可选。默认是替换同名文件
* @param moduleName 项目内的模块名
* @return
*/
public String uploadFile(MultipartFile file, ConflictPolicy policy, String moduleName) {
if (isEmpty(file)) {
return null;
}
// 生成临时文件
File localFile = null;
try {
//先从s3服务器上查找是否有同名文件
String key = s3Config.getProject() + "/" + moduleName + "/" + file.getOriginalFilename();
localFile = File.createTempFile("temp", null);
file.transferTo(localFile);
String prefix = key.substring(0, key.lastIndexOf("."));
String suffix = key.substring(key.indexOf("."));
//取出同名文件的最大number
int maxNum = getMaxVersionNum(s3Config.getBucketName(), prefix, suffix);
if (maxNum != -1) {
switch (policy) {
case NEW:
key = prefix + "(" + (++maxNum) + ")" + suffix;
break;
case RETAIN:
return "文件已存在,根据冲突策略,文件不予替换";
case REPLACE:
default:
break;
}
}
PutObjectRequest request = new PutObjectRequest(s3Config.getBucketName(), key, localFile);
// 上传文件 如果没抛异常则可认为上传成功
PutObjectResult putObjectResult = s3.putObject(request);
if (StringUtils.isNotEmpty(putObjectResult.getETag())) {
return key;
}
return null;
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (localFile != null) {
localFile.delete();
}
}
return null;
}
private int getMaxVersionNum(String bucketName, String prefix, String suffix) {
ListObjectsRequest listRequest = new ListObjectsRequest().withBucketName(bucketName).withPrefix(prefix).withMaxKeys(100);
ObjectListing objectListing = s3.listObjects(listRequest);
int value = -1;
for (S3ObjectSummary inst : objectListing.getObjectSummaries()) {
String indexStr = inst.getKey().replace(prefix, "").replace("(", "").replace(")", "").replace(suffix, "");
if (indexStr.length() == 0) {
indexStr = "0";
}
value = Math.max(value, Integer.parseInt(indexStr));
}
return value;
}
/**
* 删除单个文件
*
* @param key 根据key删除文件
* @return
*/
public void deleteObject(String key) {
if (StringUtils.isBlank(key)) {
throw new IllegalArgumentException("key can not be null");
}
s3.deleteObject(s3Config.getBucketName(), key);
}
/**
* @param key 根据key得到文件的输入流
* @return
*/
public S3ObjectInputStream getFileInputStream(String key) {
S3Object object = s3.getObject(new GetObjectRequest(s3Config.getBucketName(), key));
return object.getObjectContent();
}
/**
* 根据key得到输入流并输出到输出流
*
* @param key
* @param stream
*/
public void downloadFile(String key, OutputStream stream) {
InputStream input = getFileInputStream(key);
byte[] data = null;
try {
data = new byte[input.available()];
int len = 0;
while ((len = input.read(data)) != -1) {
stream.write(data, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (stream != null) {
try {
stream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (input != null) {
try {
input.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 根据key得到输入流并输出到输出流
*
* @param key
* @param response
*/
public void downloadFile(String key, HttpServletResponse response) {
String fileName = key;
byte[] data = null;
OutputStream stream = null;
InputStream input = getFileInputStream(key);
if (key.contains("/")) {
String[] path = key.split("/");
fileName = path[path.length - 1];
}
response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
try {
stream = response.getOutputStream();
data = new byte[input.available()];
int len = 0;
while ((len = input.read(data)) != -1) {
stream.write(data, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (stream != null) {
try {
stream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (input != null) {
try {
input.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 删除文件夹
*
* @param filePath 文件夹地址[ eg:temp/1 或 temp ]
* @param deleteAll true-递进删除所有文件(包括子文件夹);false-只删除当前文件夹下的文件,不删除子文件夹内容
*/
public void deleteFolder(String filePath, boolean deleteAll) {
ListObjectsV2Request objectsRequest = new ListObjectsV2Request();
objectsRequest.setBucketName(s3Config.getBucketName());
objectsRequest.setPrefix(filePath);
// deliter表示分隔符, 设置为/表示列出当前目录下的object, 设置为空表示列出所有的object
objectsRequest.setDelimiter(deleteAll ? "" : "/");
// 设置最大遍历出多少个对象, 一次listobject最大支持1000
objectsRequest.setMaxKeys(1000);
ListObjectsV2Result listObjectsRequest = s3.listObjectsV2(objectsRequest);
List<S3ObjectSummary> objects = listObjectsRequest.getObjectSummaries();
String[] object_keys = new String[objects.size()];
for (int i = 0; i < objects.size(); i++) {
S3ObjectSummary item = objects.get(i);
object_keys[i] = item.getKey();
}
DeleteObjectsRequest dor = new DeleteObjectsRequest(s3Config.getBucketName()).withKeys(object_keys);
s3.deleteObjects(dor);
}
/**
* 检查文件是否为空
*
* @param
* @return
*/
public boolean isEmpty(MultipartFile file) {
if (file == null || file.getSize() <= 0) {
return true;
}
return false;
}
/**
* 得到所有文件的key
*
* @return key list
*/
public List<String> getFileKeys() {
List<String> keys = new LinkedList<>();
ListObjectsRequest listRequest = new ListObjectsRequest().withBucketName(s3Config.getBucketName());
try {
ObjectListing objects = s3.listObjects(listRequest);
while (true) {
List<S3ObjectSummary> summaries = objects.getObjectSummaries();
for (S3ObjectSummary summary : summaries) {
keys.add(summary.getKey());
}
if (objects.isTruncated()) {
objects = s3.listNextBatchOfObjects(objects);
} else {
break;
}
}
} catch (Exception exception) {
exception.printStackTrace();
}
return keys;
}
public void getBizFile(List<String> keys, File targetZipFile) {
InputStream[] inputStreams = keys.stream().map(this::getFileInputStream).toArray(InputStream[]::new);
String[] strings = keys.stream().map(key -> key.split("/")[key.split("/").length - 1]).toArray(String[]::new);
ZipUtil.zip(targetZipFile, strings, inputStreams);
}
public void downBizFile(List<String> keys, HttpServletResponse response) {
File file = new File(System.currentTimeMillis() + ".zip");
getBizFile(keys, file);
OutputStream toClient = null;
try {
// 以流的形式下载文件。
BufferedInputStream fis = new BufferedInputStream(new FileInputStream(file.getPath()));
byte[] buffer = new byte[fis.available()];
fis.read(buffer);
fis.close();
// 清空response
response.reset();
toClient = new BufferedOutputStream(response.getOutputStream());
response.setCharacterEncoding("UTF-8");
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition", "attachment;filename=" + file.getName());
toClient.write(buffer);
toClient.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (toClient != null) {
try {
toClient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
//删除改临时zip包(此zip包任何时候都不需要保留,因为源文件随时可以再次进行压缩生成zip包)
file.delete();
}
}
}