aws协议实现文件管理

配置类:

java 复制代码
import com.amazonaws.ClientConfiguration;
import com.amazonaws.Protocol;
import com.amazonaws.auth.AWSCredentials;
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 org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableConfigurationProperties(AwsProperties.class)
public class AwsConfig {
    @Autowired
    AwsProperties awsProperties;

    @Bean
    AmazonS3 s3Client() {
        //设置连接时的参数
        ClientConfiguration config = new ClientConfiguration();
        //设置连接方式为HTTP,可选参数为HTTP和HTTPS
        config.setProtocol(Protocol.HTTP);
        //设置网络访问超时时间
        config.setConnectionTimeout(5000);
        config.setUseExpectContinue(true);
        //获取访问凭证
        AWSCredentials credentials = null;
        credentials = new BasicAWSCredentials(awsProperties.getAccessKeyId(),awsProperties.getSecretAccessKey());

        //设置Endpoint
        AwsClientBuilder.EndpointConfiguration end_point = null;
        end_point = new AwsClientBuilder.EndpointConfiguration(awsProperties.getEndpoint(), "");

        return AmazonS3ClientBuilder.standard()
               .withCredentials(new AWSStaticCredentialsProvider(credentials))
               .withClientConfiguration(config)
               .withEndpointConfiguration(end_point)
               .withPathStyleAccessEnabled(true).build();
    }

}
java 复制代码
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;

@Data
@ConfigurationProperties(prefix = "s3.storage")
public class AwsProperties {

    private String accessKeyId;
    private String secretAccessKey;
    private String endpoint;
    private String bucketName;

}

yml:

java 复制代码
s3:
  storage:
    accessKeyId: 
    secretAccessKey: 
    endpoint: 127.0.0.1:8999
    bucketName: 

服务层实现:

java 复制代码
import com.amazonaws.services.s3.model.PutObjectResult;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.concurrent.Future;

public interface AwsService {

	List<S3Obj> getObjListByBucketAndPath(String bucketName, String folderPath) throws Exception;

	/**
	 * 新建文件夹
	 * @param bucketName
	 * @param folderPath
	 * @return
	 * @throws Exception
	 */
	PutObjectResult addFolder(String bucketName, String folderPath) throws Exception;

	/**
	 * 删除文件夹
	 * (会删除 folderPath 路径下所有文件)
	 * @param bucketName
	 * @param folderPath
	 * @throws Exception
	 */
	void deleteFolder(String bucketName, String folderPath) throws Exception;

	/**
	 * 批量上传文件
	 * @param files
	 * @param bucketName
	 * @param folderPath
	 * @throws Exception
	 */
	Future<String> batchUpload(MultipartFile[] files, String bucketName, String folderPath);

	/**
	 * 下载文件或文件夹
	 * @param bucketName
	 * @param path 路径列表
	 * @throws Exception
	 */
	Future<String> download(String bucketName, String path, HttpServletResponse response);

}
java 复制代码
import cn.hutool.core.io.IoUtil;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.iterable.S3Objects;
import com.amazonaws.services.s3.model.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.URLEncoder;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.Future;
import static cn.hutool.core.io.file.FileWrapper.DEFAULT_CHARSET;
import static cn.hutool.core.util.ZipUtil.getZipOutputStream;

@EnableAsync
@Slf4j
@Service
public class AwsServiceImpl implements AwsService {

	@Autowired
	public AwsProperties awsProperties;

	@Autowired
	public AmazonS3 amazonS3;

	/**
	 * 根据桶和路径获取对象列表
	 * @param bucketName
	 * @return
	 */
	@Override
	public List<S3Obj> getObjListByBucketAndPath(String bucketName, String folderPath) throws Exception {
		if(!folderPath.endsWith("/")){
			folderPath = folderPath + "/";
		}
		ListObjectsV2Request req = new ListObjectsV2Request().withBucketName(bucketName).withPrefix(folderPath).withDelimiter("/");
		ListObjectsV2Result listObjectsV2Result = amazonS3.listObjectsV2(req);
		List<S3Obj> list = new ArrayList<>();

		// 遍历前缀列表
		for (String commonPrefix : listObjectsV2Result.getCommonPrefixes()) {
			S3Obj entity = new S3Obj();
			InetAddress address = InetAddress.getLocalHost();
			String hostAddress = address.getHostAddress();
			entity.setIp(hostAddress);
			String[] ids = commonPrefix.split("/");
			String name = ids[ids.length-1];
			entity.setName(name);
			entity.setPath("/" + commonPrefix);
			entity.setSize(null);
			int separatorIndex = entity.getName().lastIndexOf(".");
			if (separatorIndex < 0) {
				entity.setType("folder");
			}
			entity.setLastModified(null);
			list.add(entity);
		}

		// 遍历 folderPath 下所有 对象
		for ( S3ObjectSummary summary : S3Objects.withPrefix(amazonS3, bucketName, folderPath) ) {
			for (S3ObjectSummary summ : listObjectsV2Result.getObjectSummaries()) {
				if(summ.getKey().equals(summary.getKey())){
					if(!folderPath.equals(("/"+summ.getKey()))){
						S3Obj entity = new S3Obj();
						InetAddress address = InetAddress.getLocalHost();
						String hostAddress = address.getHostAddress();
						entity.setIp(hostAddress);
						int index = summary.getKey().lastIndexOf("/");
						if(index < 0){
							entity.setName(summary.getKey());
						}else{
							entity.setName(summary.getKey().substring(index + 1).toLowerCase());
						}
						entity.setPath("/"+summary.getKey());
						DecimalFormat df = new DecimalFormat("#.00");
						entity.setSize(df.format((double) summ.getSize() / 1024));
						int separatorIndex = entity.getName().lastIndexOf(".");
						if (separatorIndex < 0) {
							entity.setType("folder");
						}else{
							entity.setType(entity.getName().substring(separatorIndex + 1).toLowerCase());
						}
						Date lastModified = summ.getLastModified();
						entity.setLastModified(lastModified);
						list.add(entity);
					}
				}
			}

		}

		if (list.size() <= 0){
			return list;
		}

		// 使用 Comparator 进行降序排序,处理字段 lastModified 可能为空的情况
		list.sort((o1, o2) -> {
			if (o1.getLastModified() == null && o2.getLastModified() == null) {
				return 0; // 如果两个对象都为空,则认为它们相等
			} else if (o1.getLastModified() == null) {
				return 1; // 如果第一个对象为空,则认为它比第二个对象大
			} else if (o2.getLastModified() == null) {
				return -1; // 如果第二个对象为空,则认为它比第一个对象大
			} else {
				return o2.getLastModified().compareTo(o1.getLastModified()); // 否则按降序比较
			}
		});

		return list;
	}

	@Override
	public PutObjectResult addFolder(String bucketName, String folderPath) throws Exception {
		if(!folderPath.endsWith("/")){
			folderPath = folderPath + "/";
		}
		PutObjectResult object = amazonS3.putObject(bucketName, folderPath, "");
		return object;
	}

	@Override
	public void deleteFolder(String bucketName, String path) throws Exception {
		AwsFileDto file = isFile(path);

		if ("file".equals(file.getObjType())){
			amazonS3.deleteObject(bucketName, path);
		}

		else if ("folder".equals(file.getObjType())){
			for (S3ObjectSummary summary : S3Objects.withPrefix(amazonS3, bucketName, path)) {
				amazonS3.deleteObject(bucketName,"/" + summary.getKey());
			}
		}

	}

	@Async
	@Override
	public Future<String> batchUpload(MultipartFile[] files, String bucketName, String folderPath) {
		try{
			if(!folderPath.endsWith("/")){
				folderPath = folderPath + "/";
			}
			for (MultipartFile file : files){
				String localFileName = file.getOriginalFilename();
				File uploadFile = new File(localFileName);
				FileUtils.copyInputStreamToFile(file.getInputStream(), uploadFile);
				String filePath = folderPath + localFileName;
				amazonS3.putObject(bucketName, filePath, uploadFile);

				if(uploadFile.exists()){
					uploadFile.delete();
				}
			}

			return new AsyncResult<>("上传成功");
		}catch (Exception e){
			log.error("batchUpload:{}", e);
			return new AsyncResult<>("上传失败");
		}
	}

	public AwsFileDto isFile(String path){
		AwsFileDto dto = new AwsFileDto();

		int index = path.lastIndexOf("/");
		String pathName, objName, objType;
		if (index != -1 && index < path.length() - 1){
			pathName = path.substring(index);
			objName = path.substring(index + 1);
			objType = "file";	// 文件

			dto.setPathName(pathName);
			dto.setObjName(objName);
			dto.setObjType(objType);
		} else {
			String subPath = path.substring(0, path.length() - 1);

			pathName = subPath.substring(subPath.lastIndexOf("/"));
			objName = subPath.substring(subPath.lastIndexOf("/") + 1);
			objType = "folder";  // 文件夹

			dto.setPathName(pathName);
			dto.setObjName(objName);
			dto.setObjType(objType);
		}
		return dto;
	}

	@Async
	@Override
	public Future<String> download(String bucketName, String path, HttpServletResponse response) {
		try{
			AwsFileDto file = isFile(path);

			// 文件下载
			if ("file".equals(file.getObjType())){
				S3Object object = amazonS3.getObject(bucketName, path);
				if(object != null){
					//log.info("ETag: [{}]", object.getObjectMetadata().getETag());
					InputStream inputStream = object.getObjectContent();
					try {
						response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(file.getObjName(), "UTF-8"));
						OutputStream outputStream = response.getOutputStream();
						// 使用 Hutool 的 IoUtil 进行流的复制
						IoUtil.copy(inputStream, outputStream);
					} catch (Exception e) {
						log.error("下载文件异常", e);
						throw new Exception("下载文件异常!");
					}
				}
			}

			// 压缩包下载 @todo
			else if ("folder".equals(file.getObjType())){

			}

			return new AsyncResult<>("下载成功");
		}catch (Exception e){
			log.error("download:{}", e);
			return new AsyncResult<>("下载失败");
		}
	}

}
java 复制代码
@Data
public class S3Obj {

	@ApiModelProperty(value = "文件名",position = 1 )
	private String name;

	@ApiModelProperty(value = "路径",position = 2 )
	private String path;

	@ApiModelProperty(value = "文件大小 单位kb",position = 3 )
	private String size;

	@ApiModelProperty(value = "文件类型 folder:文件夹,doc:文档,text:文本,jpg,png:照片等",position = 4 )
	private String type;

	@ApiModelProperty(value = "地址",position = 4 )
	private String ip;

	@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
	@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone="GMT+8")
	@ApiModelProperty(value = "最后修改时间",position = 5 )
	private Date lastModified;

}
相关推荐
计算机毕设指导62 分钟前
基于Springboot美食推荐商城系统【附源码】
java·前端·spring boot·后端·spring·tomcat·美食
web150850966413 分钟前
程序包org.springframework.boot不存在
java·spring boot·spring
zhangxueyi9 分钟前
MySQL之企业面试题:InnoDB存储引擎组成部分、作用
java·数据库·mysql·面试·innodb
一条小小yu14 分钟前
java 从零开始手写 redis(六)redis AOF 持久化原理详解及实现
java·redis·spring
Bling_25 分钟前
Springboot Bean创建流程、三种Bean注入方式(构造器注入、字段注入、setter注入)、循坏依赖问题
java·spring boot·spring·容器
开疆智能40 分钟前
机器人技术:ModbusTCP转CCLINKIE网关应用
java·服务器·科技·机器人·自动化
心向阳光的天域1 小时前
黑马跟学.苍穹外卖.Day03
java·开发语言·spring boot
对酒当歌丶人生几何1 小时前
SpringBoot实现国际化
java·spring boot·后端·il8n
雪芽蓝域zzs1 小时前
JavaWeb开发(九)JSP技术
java·开发语言
上海拔俗网络1 小时前
“智能筛查新助手:AI智能筛查分析软件系统如何改变我们的生活
java·团队开发