package com.fdkankan.fyun.oss;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.FileUtil;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.model.DeleteObjectsRequest;
import com.aliyun.oss.model.DeleteObjectsResult;
import com.aliyun.oss.model.ListObjectsRequest;
import com.aliyun.oss.model.ObjectListing;
import com.aliyun.oss.model.ObjectMetadata;
import com.aliyun.oss.model.PutObjectResult;
import com.aliyun.oss.model.*;
import com.amazonaws.HttpMethod;
import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.CannedAccessControlList;
import com.amazonaws.services.s3.model.DeleteObjectsRequest.KeyVersion;
import com.amazonaws.services.s3.model.GeneratePresignedUrlRequest;
import com.amazonaws.services.s3.model.GetObjectRequest;
import com.amazonaws.services.s3.model.PutObjectRequest;
import com.amazonaws.services.s3.model.*;
import com.fdkankan.fyun.constant.StorageType;
import com.fdkankan.fyun.model.StreamGobbler;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import java.io.*;
import java.net.FileNameMap;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Component
public class UploadToOssUtil {

	@Value("${oss.point:http://oss-cn-shenzhen-internal.aliyuncs.com}")
	private String point;

	@Value("${oss.key:LTAIUrvuHqj8pvry}")
	private String key;

	@Value("${oss.secrey:JLOVl0k8Ke0aaM8nLMMiUAZ3EiiqI4}")
	private String secrey;

	@Value("${oss.bucket:4dkankan}")
	private String bucket;

	@Value("${oss.sdk:4dscene}")
	private String bucketSdk;

	@Value("${upload.type:oss}")
	private String type;

	@Value("${aws.s3key:AKIAWCV5QFZ3ZNELKYUY}")
	private String s3key;

	@Value("${aws.s3secrey:epS5ghyR4LJ7rxk/qJO9ZYh6m9Oz6g5haKDu4yws}")
	private String s3secrey;

	@Value("${aws.s3bucket:4dkankan}")
	private String s3bucket;

	@Value("${local.path:/home/4dkankan}")
	private String localPath;

	/**
	 * oss文件上传命令
	 * 第一个参数是oss路径，要包含bucket名称
	 * 第二个参数是本地文件路径
	 */
	private static final String UPLOAD_SH = "bash /opt/ossutil/upload.sh %s %s";

	public static final String FYUN_UPLOAD = "sudo bash /opt/ossutil/fyun-upload.sh %s %s /%s %s %s";

	//上传的数据是byte[]，key是上传后的文件名
	public void upload(String bucket, byte[] data,String key1) throws IOException{
		log.info("开始上传文件 源路径：{},目标路径：{},type:{}" , new String(data, "UTF-8"),key1,type);
		StorageType storageType = StorageType.get(type);
		switch (storageType){
			case OSS:
				uploadOss(bucket, data,key1);
				break;
			case AWS:
				uploadAws(bucket, data,key1);
				break;
			case LOCAL:
				uploadLocal(data,key1);
				break;
		}
	}
	public void upload(String bucket, String filePath, String key1) {
		log.info("开始上传文件 源路径：{},目标路径：{},type:{}" , filePath,key1,type);
		StorageType storageType = StorageType.get(type);
		switch (storageType){
			case OSS:
				uploadOss(bucket, filePath,key1);
				break;
			case AWS:
				uploadAws(bucket, filePath,key1);
				break;
			case LOCAL:
				uploadLocal(filePath,key1);
				break;
		}
	}

	/**
	 * 通过脚本上传
	 * @param filePath
	 * @param key
	 */
	public void uploadBySh(String bucket, String filePath, String key) {
		String command = String.format(FYUN_UPLOAD, bucket, filePath, key, type, "file");
		try {
			log.info("开始上传文件, ossPath:{}, srcPath:{}", key, filePath);
			callshell(command);
			log.info("上传文件完毕, ossPath:{}, srcPath:{}", key, filePath);
		} catch(Exception e) {
			log.error("上传文件失败, ossPath:{}, srcPath:{}", key, filePath);
			log.error("上传文件失败", e);
		}
	}

	public static void callshell(String command){
		try {
			Long start = System.currentTimeMillis();
			Process process = Runtime.getRuntime().exec(command);
			StreamGobbler errorGobbler = new StreamGobbler(process.getErrorStream(), "ERROR");
			errorGobbler.start();
			StreamGobbler outGobbler = new StreamGobbler(process.getInputStream(), "STDOUT");
			outGobbler.start();
			process.waitFor();
			log.info("脚本{}执行完毕,用时：{}ms",command,System.currentTimeMillis()-start);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void uploadSdk(String bucket, String filePath, String key1) {
		log.info("开始上传文件 源路径：{},目标路径：{},type:{}" , filePath,key1,type);
		switch (type){
			case "oss":uploadSdkOss(bucket, filePath, key1); break;
			case "aws": uploadAws(bucket, filePath, key1); break;
			case "local":uploadLocal(filePath,key1);  break;
		}
	}
	public void upload2(String bucket, String filePath, String key1) {
		log.info("开始上传文件 源路径：{},目标路径：{},type:{}" , filePath,key1,type);
		switch (type){
			case "oss":upload2Oss(bucket, filePath,key1); break;
			case "aws": uploadAws(bucket, filePath,key1); break;
			case "local":uploadLocal(filePath,key1);  break;
		}
	}
	public void delete(String bucket, String key1) throws IOException{
		switch (type){
			case "oss":deleteOss(bucket, key1); break;
			case "aws": deleteS3Object(bucket, key1); break;
			case "local":FileUtil.del(key1);  break;
		}
	}

	/**
	 * 删除目录或者文件
	 * @param prefix
	 * @return
	 */
	public int deleteFile(String bucket, String prefix){
		switch (type){
			case "oss":deleteOssFile(bucket, prefix); break;
			case "aws": deleteAwsFile(bucket, prefix); break;
			case "local":FileUtil.del(prefix);  break;
		}
		return 1;
	}

	public void deleteOss(String bucket, String objectName){
		OSSClient ossClient = new OSSClient(point, key, secrey);
		try {
			ossClient.deleteObject(bucket, objectName);
		} catch (Exception e) {
			log.error("OSS删除文件失败,key=" + objectName);
		}finally {
			if(ossClient != null){
				ossClient.shutdown();
			}
		}
	}

	public void deleteOssFile(String bucket, String prefix){
		int maxKeys = 200;
		OSSClient ossClient = new OSSClient(point, key, secrey);
		try {

			String nextMarker = null;
			ObjectListing objectListing;

			do {
				objectListing = ossClient.listObjects(new ListObjectsRequest(bucket).withPrefix(prefix).withMarker(nextMarker).withMaxKeys(maxKeys));
				List<OSSObjectSummary> sums = objectListing.getObjectSummaries();
				if (CollUtil.isEmpty(sums)) {
					return;
				}
				List<String> keys = new ArrayList<>();
				for (OSSObjectSummary sum : sums) {
					keys.add(sum.getKey());
				}
				DeleteObjectsRequest deleteObjectsRequest =
					new DeleteObjectsRequest(bucket).withKeys(keys).withEncodingType("url");
				DeleteObjectsResult deleteObjectsResult = ossClient
					.deleteObjects(deleteObjectsRequest);
				List<String> deletedObjects = deleteObjectsResult.getDeletedObjects();
				try {
					for (String deletedObject : deletedObjects) {
						String decode = URLDecoder.decode(deletedObject, "UTF-8");
						log.info("删除oss文件:{}", decode);
					}
				} catch (UnsupportedEncodingException e) {
					e.printStackTrace();
				}
			}while (objectListing.isTruncated());
		}catch (Exception  e){
			e.printStackTrace();
		}finally {
			if(ossClient != null){
				ossClient.shutdown();
			}
		}
	}

	private void deleteAwsFile(String bucket, String prefix){

		int maxKeys = 200;
		String nextMaker = null;
		BasicAWSCredentials awsCreds = new BasicAWSCredentials(s3key, s3secrey);
		AmazonS3 s3 = AmazonS3ClientBuilder.standard()
			.withCredentials(new AWSStaticCredentialsProvider(awsCreds))
			.withRegion(Regions.EU_WEST_2)
			.build();
		try {
			com.amazonaws.services.s3.model.ListObjectsRequest listObjectsRequest = new com.amazonaws.services.s3.model.ListObjectsRequest();
			listObjectsRequest.setBucketName(bucket);
			listObjectsRequest.setPrefix(prefix);
			listObjectsRequest.setMaxKeys(maxKeys);

			com.amazonaws.services.s3.model.ObjectListing objectListing;
			do{
				listObjectsRequest.setMarker(nextMaker);
				objectListing = s3.listObjects(listObjectsRequest);
				List<S3ObjectSummary> objectSummaries = objectListing.getObjectSummaries();
				List<KeyVersion> keys =objectSummaries.stream().map(summary->new KeyVersion(summary.getKey())).collect(Collectors.toList());

				com.amazonaws.services.s3.model.DeleteObjectsRequest multiObjectDeleteRequest =
					new com.amazonaws.services.s3.model.DeleteObjectsRequest(bucket)
					.withKeys(keys)
					.withQuiet(false);
				com.amazonaws.services.s3.model.DeleteObjectsResult delObjRes = s3.deleteObjects(multiObjectDeleteRequest);
				int successfulDeletes = delObjRes.getDeletedObjects().size();
				log.info("删除aws文件成功，删除文件数;{}", successfulDeletes);
				nextMaker = objectListing.getNextMarker();
			}while (objectListing.isTruncated());
		}catch (Exception e){
			log.error("删除was文件失败，path="+prefix, e);
		}finally {
			if(s3 != null){
				s3.shutdown();
			}
		}
	}

	public void uploadOss(String bucket, byte[] data,String objectName){
		OSSClient ossClient = new OSSClient(point, key, secrey);
		try {
			ossClient.putObject(bucket, objectName, new ByteArrayInputStream(data));
		} catch (Exception e) {
			log.error("oss上传文件失败", e);
		}finally {
			if(ossClient != null){
				ossClient.shutdown();
			}
		}
	}
	public void uploadAws(String bucket, byte[] data,String objectName){
		BasicAWSCredentials awsCreds = new BasicAWSCredentials(s3key, s3secrey);
		AmazonS3 s3 = AmazonS3ClientBuilder.standard()
			.withCredentials(new AWSStaticCredentialsProvider(awsCreds))
			.withRegion(Regions.EU_WEST_2)
			.build();
		try {
			com.amazonaws.services.s3.model.ObjectMetadata metadata = new com.amazonaws.services.s3.model.ObjectMetadata();
			PutObjectRequest request = new PutObjectRequest(bucket, objectName, new ByteArrayInputStream(data), metadata);
			request.withCannedAcl(CannedAccessControlList.PublicRead);
			s3.putObject(request);
		}catch (Exception e){
			log.error("s3上传文件失败", e);
		}finally {
			if(s3 != null){
				s3.shutdown();
			}
		}
	}
	public void uploadLocal(byte[] data,String key1){
		InputStream in = new ByteArrayInputStream(data);
		File file = new File(key1);
		String path = key1.substring(0, key1.lastIndexOf("/"));
		if (!file.exists()) {
			new File(path).mkdir();
		}
		FileOutputStream fos = null;
		try {
			fos = new FileOutputStream(file);
			int len = 0;
			byte[] buf = new byte[1024];
			while ((len = in.read(buf)) != -1) {
				fos.write(buf, 0, len);
			}
			fos.flush();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (null != fos) {
				try {
					fos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}


	public void uploadOss(String bucket, String filePath, String key1){
		OSSClient ossClient = new OSSClient(point, key, secrey);
		try {
			File file = new File(filePath);
			if (!file.exists()) {
				log.error("要上传的文件不存在：" + filePath);
				return;
			}
			ObjectMetadata metadata = new ObjectMetadata();
			if(filePath.contains(".jpg")){
				metadata.setContentType("image/jpeg");
			}
			ossClient.putObject(bucket, key1, new File(filePath), metadata);

		} catch (Exception e) {
			log.error(e.toString() + filePath);
		} finally {
			ossClient.shutdown();
		}
	}

	public void uploadAws(String bucket, String filePath, String key1){
		try{
			uploadS3File(bucket, filePath, key1);
		}catch (Exception e){
			e.printStackTrace();
		}
	}
	public void uploadLocal(String filePath, String key1){
		try {
			File srcFile = new File(filePath);
			File file = new File(localPath + key1);
			FileUtils.copyFile(srcFile,file);
		}catch (Exception e){
			e.printStackTrace();
		}
	}


	public void uploadSdkOss(String bucket, String filePath, String key1){
		OSSClient ossClient = new OSSClient(point, key, secrey);
		try {
			File file = new File(filePath);
			if (!file.exists()) {
				log.error("要上传的文件不存在：" + filePath);
				return;
			}
			ObjectMetadata metadata = new ObjectMetadata();
			if(filePath.contains(".jpg")){
				metadata.setContentType("image/jpeg");
			}
			ossClient.putObject(bucket, key1, new File(filePath), metadata);

		} catch (Exception e) {
			log.error(e.toString() + filePath);
		}
	}

	public void upload2Oss(String bucket, String filePath, String key1){
		OSSClient ossClient = new OSSClient(point, key, secrey);
		try {
			ObjectMetadata metadata = new ObjectMetadata();
			if(filePath.contains(".jpg")){
				metadata.setContentType("image/jpeg");
			}
			if(filePath.contains(".mp4")){
				metadata.setContentType("video/mp4");
			}
			if(filePath.contains(".mp3")){
				metadata.setContentType("audio/mp3");
			}
			ossClient.putObject(bucket, key1, new File(filePath), metadata);
		} catch (Exception e) {
			log.error(e.toString() + filePath);
		}
	}

	//上传的数据是文件夹，参数是文件夹路径，key是上传后的文件名
	public void uploadMulFiles(String bucket, Map<String, String> filepaths) {
		if (filepaths == null) {
			return;
		}
		Long start = System.currentTimeMillis();
		log.info("开始批量上传文件：");
		if (filepaths.size() > 50) {
			filepaths.entrySet().parallelStream().forEach(entry->{
				upload2(bucket, entry.getKey(), entry.getValue());
			});
		} else {
			filepaths.entrySet().parallelStream().forEach(entry->{
				upload(bucket, entry.getKey(), entry.getValue());
			});
		}
		log.info("批量上传文件结束，用时:{}" ,(System.currentTimeMillis() - start));
	}



	public Map<String, String> getUploadS3Url(List<String> urls){
		if(urls == null || urls.size() <= 0){
			return null;
		}
		BasicAWSCredentials awsCred = new BasicAWSCredentials(s3key, s3secrey);

		AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
				.withCredentials(new AWSStaticCredentialsProvider(awsCred))
				.withRegion(Regions.EU_WEST_2)
				.build();

		// Set the pre-signed URL to expire after one hour.
		java.util.Date expiration = new java.util.Date();
		long expTimeMillis = expiration.getTime();
		expTimeMillis += 1000 * 60 * 60 * 8;
		expiration.setTime(expTimeMillis);

		//生成预签名URL
		log.info("生成预签名URL");
		GeneratePresignedUrlRequest generatePresignedUrlRequest = null;
		URL url = null;
		Map<String, String> map = new HashMap();
		for(String path : urls){
//			if(path.contains(".jpg") || path.contains("png")){
//				generatePresignedUrlRequest = new GeneratePresignedUrlRequest(s3bucket, path)
//						.withMethod(HttpMethod.PUT)
//						.withExpiration(expiration)
//						.withContentType("image/jpeg");
//			}else {
				generatePresignedUrlRequest = new GeneratePresignedUrlRequest(s3bucket, path)
						.withMethod(HttpMethod.PUT)
						.withExpiration(expiration);
//			}
			url = s3Client.generatePresignedUrl(generatePresignedUrlRequest);
			map.put(path, url.toString());
		}
		return map;
	}


	public String upload5(String filePath, String key1) {
		OSSClient ossClient = new OSSClient(point, key, secrey);
		PutObjectResult result = null;
		try {
			File file = new File(filePath);
			if (!file.exists()) {
				log.error("要上传的文件不存在：" + filePath);
			}


			result = ossClient.putObject(bucket, key1, new File(filePath));

		} catch (Exception e) {
			log.error(e.toString() + filePath);
		}

		log.info(" getETag : " + result.getETag());
		log.info("1 : " + result.toString());
		log.info("2 : " + result.getRequestId());
		log.info("3 : " + result.getClientCRC());
		log.info("4 : " + result.getResponse());
		log.info("5 : " + result.getServerCRC());
		return result.getETag();
	}


	//海外亚马逊s3


	/**
	 * s3上传文件流
	 *
	 * @param file       文件
	 * @param updatePath 上传路径[ eg: xxx/xxx ]
	 */
	public String updateS3LoadFile(String bucket, MultipartFile file, String updatePath) {

		if (isEmpty(file)) {
			return null;
		}

		/**
		 * 创建s3对象
		 */
		BasicAWSCredentials awsCreds = new BasicAWSCredentials(s3key, s3secrey);
		AmazonS3 s3 = AmazonS3ClientBuilder.standard()
				.withCredentials(new AWSStaticCredentialsProvider(awsCreds))
				.withRegion(Regions.EU_WEST_2)
				.build();

		try {
			// 创建临时文件，程序运行结束，会自动删除
			File localFile = File.createTempFile("temp", null);
			// 把文件写入内存中
			file.transferTo(localFile);

			// 指定要上传到服务器上的路径
			String key = updatePath;

			// 设置文件并设置公读
			PutObjectRequest request = new PutObjectRequest(bucket, key, localFile);
			request.withCannedAcl(CannedAccessControlList.PublicRead);

			// 上传文件
			com.amazonaws.services.s3.model.PutObjectResult putObjectResult = s3.putObject(request);
			if (StringUtils.isNotEmpty(putObjectResult.getETag())) {
				System.out.println("success");
				return key;
			}
			return null;

		} catch (IOException e) {
		}
		return null;
	}

	/**
	 * s3上传文件
	 * @param filePath
	 * @param key1
	 * @throws IOException
     */
	private void uploadS3File(String bucket, String filePath, String key1) throws Exception {
		/**
		 * 创建s3对象
		 */
		BasicAWSCredentials awsCreds = new BasicAWSCredentials(s3key, s3secrey);
		AmazonS3 s3 = AmazonS3ClientBuilder.standard()
			.withCredentials(new AWSStaticCredentialsProvider(awsCreds))
			.withRegion(Regions.EU_WEST_2)
			.build();
		try{
			File file = new File(filePath);
			if(!file.exists()){
				log.info("要上传s3的文件不存在");
				return;
			}

			// 设置文件并设置公读
			com.amazonaws.services.s3.model.ObjectMetadata metadata = new com.amazonaws.services.s3.model.ObjectMetadata();
			if(filePath.contains(".jpg")){
				metadata.setContentType("image/jpeg");
			}
			if(filePath.contains(".png")){
				metadata.setContentType("image/png");
			}
			PutObjectRequest request = new PutObjectRequest(bucket, key1, file);
			request.withCannedAcl(CannedAccessControlList.PublicRead);
			request.withMetadata(metadata);

			// 上传文件
			com.amazonaws.services.s3.model.PutObjectResult putObjectResult = s3.putObject(request);
			if (StringUtils.isNotEmpty(putObjectResult.getETag())) {
				log.info("s3上传文件成功：" + key1);
			}
		}catch (Exception e){
			throw e;
		}finally {
			s3.shutdown();
		}

	}

	/**
	 * 删除单个文件
	 *
	 * @param objectName 文件路径[ eg: /head/xxxx.jpg ]
	 * @return
	 */
	public void deleteS3Object(String bucket, String objectName) {

		/**
		 * 创建s3对象
		 */
		BasicAWSCredentials awsCreds = new BasicAWSCredentials(s3key, s3secrey);
		AmazonS3 s3 = AmazonS3ClientBuilder.standard()
				.withCredentials(new AWSStaticCredentialsProvider(awsCreds))
				.withRegion(Regions.EU_WEST_2)
				.build();

		if (objectName.startsWith("/")) {
			objectName = objectName.substring(1);
		}

		try {
			s3.deleteObject(bucket, objectName);
		} catch (Exception e) {
			log.error("s3删除文件失败,key="+objectName, e);
		}finally {
			if(s3 != null){
				s3.shutdown();
			}
		}
	}



	/**
	 * 获取文件类型
	 */
	public static String getContentType(String filePath){
		FileNameMap fileNameMap = URLConnection.getFileNameMap();
		String contentType = fileNameMap.getContentTypeFor(filePath);
		System.out.println(contentType);
		return contentType;

	}

	/**
	 * 检查文件是否为空
	 *
	 * @param imageFile
	 * @return
	 */
	private static boolean isEmpty(MultipartFile imageFile) {
		if (imageFile == null || imageFile.getSize() <= 0) {
			return true;
		}
		return false;
	}

	private static MultipartFile getMulFileByPath(String picPath) {
		FileItem fileItem = createFileItem(picPath);
		MultipartFile mfile = new CommonsMultipartFile(fileItem);
		return mfile;
	}

	private static FileItem createFileItem(String filePath) {
		FileItemFactory factory = new DiskFileItemFactory(16, null);
		String textFieldName = "textField";
		int num = filePath.lastIndexOf(".");
		String extFile = filePath.substring(num);
		FileItem item = factory.createItem(textFieldName, "text/plain", true,
				"MyFileName" + extFile);
		File newfile = new File(filePath);
		int bytesRead = 0;
		byte[] buffer = new byte[8192];
		try
		{
			FileInputStream fis = new FileInputStream(newfile);
			OutputStream os = item.getOutputStream();
			while ((bytesRead = fis.read(buffer, 0, 8192))
					!= -1)
			{
				os.write(buffer, 0, bytesRead);
			}
			os.close();
			fis.close();
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
		return item;
	}

	public List<String> listKeys(String bucket, String sourcePath){
		StorageType storageType = StorageType.get(type);
		switch (storageType){
			case OSS:
				return this.listKeysFromAli(bucket, sourcePath);
			case AWS:
				return this.listKeysFromAws(bucket, sourcePath);
			case LOCAL:
				return this.listKeysFromLocal(sourcePath);
		}
		return null;
	}

	/**
	 * 获得文件列表-阿里云
	 * @return
	 */
	public List<String> listKeysFromAli(String bucket, String sourcePath) {
		List<String> keyList = new ArrayList<>();
		OSSClient ossClient = new OSSClient(point, key, secrey);
		try {
			boolean flag = true;
			String nextMaker = null;
			ListObjectsRequest listObjectsRequest = new ListObjectsRequest(bucket);
			//指定下一级文件
			listObjectsRequest.setPrefix(sourcePath);
			//设置分页的页容量
			listObjectsRequest.setMaxKeys(200);
			do
			{
				//获取下一页的起始点，它的下一项
				listObjectsRequest.setMarker(nextMaker);
				ObjectListing objectListing = ossClient.listObjects(listObjectsRequest);
				List<OSSObjectSummary> objectSummaries = objectListing.getObjectSummaries();
				List<String> collect = objectSummaries.stream().map(summary -> {
					return summary.getKey();
				}).collect(Collectors.toList());
				if(CollUtil.isNotEmpty(collect)){
					keyList.addAll(collect);
				}
				nextMaker = objectListing.getNextMarker();
				//全部执行完后，为false
				flag = objectListing.isTruncated();
			} while (flag);
		}catch (Exception e){
			log.error("获取文件列表失败，path="+sourcePath, e);
		}finally {
			if(ossClient != null){
				ossClient.shutdown();
			}
		}


		ossClient.shutdown();

		return keyList;
	}

	/**
	 * 获得文件列表-亚马逊
	 * @return
	 */
	public List<String> listKeysFromAws(String bucket, String sourcePath) {
		List<String> keyList = new ArrayList<>();

		BasicAWSCredentials awsCreds = new BasicAWSCredentials(s3key, s3secrey);
		AmazonS3 s3 = AmazonS3ClientBuilder.standard()
			.withCredentials(new AWSStaticCredentialsProvider(awsCreds))
			.withRegion(Regions.EU_WEST_2)
			.build();

		try {
			boolean flag = true;
			String nextMaker = null;
			com.amazonaws.services.s3.model.ListObjectsRequest listObjectsRequest = new com.amazonaws.services.s3.model.ListObjectsRequest();
			listObjectsRequest.setBucketName(bucket);
			listObjectsRequest.setPrefix(sourcePath);
			listObjectsRequest.setMaxKeys(200);

			do{
				listObjectsRequest.setMarker(nextMaker);
				com.amazonaws.services.s3.model.ObjectListing objectListing = s3.listObjects(listObjectsRequest);
				List<S3ObjectSummary> objectSummaries = objectListing.getObjectSummaries();
				List<String> collect =objectSummaries.stream().map(summary->{
					return summary.getKey();
				}).collect(Collectors.toList());
				if(CollUtil.isNotEmpty(collect)){
					keyList.addAll(collect);
				}
				nextMaker = objectListing.getNextMarker();
				flag = objectListing.isTruncated();
			}while (flag);
		}catch (Exception e){
			log.error("获取文件列表失败，path="+sourcePath, e);
		}finally {
			if(s3 != null){
				s3.shutdown();
			}
		}
		return keyList;
	}

	/**
	 * 获得文件列表-阿里云
	 * @return
	 */
	public List<String> listKeysFromLocal(String sourcePath) {
		List<String> keyList = new ArrayList<>();
		return keyList;
	}

	/**
	 * <p>
	        拷贝目录
	 * </p>
	 * @author dengsixing
	 * @date 2022/1/18
	 * @param sourcePath
	 * @param targetPath
	 **/
	public void copyFiles(String sourceBucketName, String sourcePath, String targetBucketName, String targetPath) throws IOException {
		StorageType storageType = StorageType.get(type);
		switch (storageType){
			case OSS:
				this.copyFilesFromAli(sourceBucketName, sourcePath, targetBucketName, targetPath);
				break;
			case AWS:
				this.copyFilesFromAws(sourceBucketName, sourcePath, targetBucketName, targetPath);
				break;
			case LOCAL: this.copyFilesFromLocal(sourcePath, targetPath);
		}
	}

	/**
	 * <p>
	 拷贝文件
	 * </p>
	 * @author dengsixing
	 * @date 2022/1/18
	 * @param sourceKey
	 * @param targetKey
	 **/
	public void copyObject(String sourceBucketName, String sourceKey, String targetBucketName, String targetKey) throws IOException {
		StorageType storageType = StorageType.get(type);
		switch (storageType){
			case OSS:
				this.copyObjectFromAli(sourceBucketName, sourceKey, targetBucketName, targetKey);
				break;
			case AWS:
				this.copyObjectFromAws(sourceBucketName, sourceKey, targetBucketName, targetKey);
				break;
		}
	}

	/**
	 * <p>
	 拷贝-阿里云
	 * </p>
	 * @author dengsixing
	 * @date 2022/1/18
	 * @param sourcePath
	 * @param targetPath
	 **/
	public void copyObjectFromAli(String sourceBucketName, String sourcePath, String targetBucketName, String targetPath) throws IOException {

		// 创建OSSClient实例。
		OSSClient ossClient = new OSSClient(point, key, secrey);
		// 复制文件
		log.info("开始复制：" + sourcePath);
		ossClient.copyObject(sourceBucketName, sourcePath, targetBucketName, targetPath);
		log.info("复制成功：" + sourcePath);
		ossClient.shutdown();
	}



	/**
	 * <p>
	 拷贝-阿里云
	 * </p>
	 * @author dengsixing
	 * @date 2022/1/18
	 * @param sourcePath
	 * @param targetPath
	 **/
	public void copyFilesFromAli(String sourceBucketName, String sourcePath, String targetBucketName, String targetPath) throws IOException {

		//获取源文件列表
		List<String> sourceKeyList = this.listKeysFromAli(sourceBucketName, sourcePath);
		if(CollUtil.isEmpty(sourceKeyList)){
			return;
		}
		// 创建OSSClient实例。
		OSSClient ossClient = new OSSClient(point, key, secrey);
		// 复制文件
		sourceKeyList.parallelStream().forEach(key -> {
			log.info("开始复制：" + key);
			ossClient.copyObject(sourceBucketName, key, targetBucketName, key.replace(sourcePath, targetPath));
			log.info("复制成功：" + key);
		});

		ossClient.shutdown();
	}


	/**
	 * <p>
	 拷贝-亚马逊
	 * </p>
	 * @author dengsixing
	 * @date 2022/1/18
	 * @param sourcePath
	 * @param targetPath
	 **/
	public void copyFilesFromAws(String sourceBucketName, String sourcePath, String targetBucketName, String targetPath){

		try {
			List<String> sourceKeyList = this.listKeysFromAws(sourceBucketName, sourcePath);
			/**
			 * 创建s3对象
			 */
			BasicAWSCredentials awsCreds = new BasicAWSCredentials(s3key, s3secrey);
			AmazonS3 s3 = AmazonS3ClientBuilder.standard()
				.withCredentials(new AWSStaticCredentialsProvider(awsCreds))
				.withRegion(Regions.EU_WEST_2)//s3 地区位置
				.build();

			// 复制文件
			sourceKeyList.parallelStream().forEach(key -> {
				log.info("开始复制：" + key);
				com.amazonaws.services.s3.model.CopyObjectRequest request =
					new com.amazonaws.services.s3.model.CopyObjectRequest(sourceBucketName, key, targetBucketName, key.replace(sourcePath, targetPath));
				request.withCannedAccessControlList(CannedAccessControlList.PublicRead);
				s3.copyObject(request);
				log.info("复制成功：" + key);
			});
			s3.shutdown();
		} catch (Exception ase) {
			log.error("amazonS拷贝异常 " + ase.getMessage(), ase);
		}
	}

	/**
	 * <p>
	 拷贝-亚马逊
	 * </p>
	 * @author dengsixing
	 * @date 2022/1/18
	 * @param sourceKey
	 * @param targetKey
	 **/
	public void copyObjectFromAws(String sourceBucketName, String sourceKey, String targetBucketName, String targetKey){
			BasicAWSCredentials awsCreds = new BasicAWSCredentials(s3key, s3secrey);
			AmazonS3 s3 = AmazonS3ClientBuilder.standard()
				.withCredentials(new AWSStaticCredentialsProvider(awsCreds))
				.withRegion(Regions.EU_WEST_2)//s3 地区位置
				.build();
			// 复制文件
			log.info("开始复制：" + sourceKey);
			s3.copyObject(sourceBucketName, sourceKey, targetBucketName, targetKey);
			log.info("复制成功：" + sourceKey);
			s3.shutdown();
	}

	/**
	 * <p>
	 拷贝-本地
	 * </p>
	 * @author dengsixing
	 * @date 2022/1/18
	 * @param sourcePath
	 * @param targetPath
	 **/
	public void copyFilesFromLocal(String sourcePath, String targetPath) throws IOException {
		// TODO: 2022/1/21

	}

	/**
	 * 获取文件内容
	 * @param bucketName
	 * @param objectName
	 * @return
	 */
	public String getObjectContent(String bucketName, String objectName){
		StorageType storageType = StorageType.get(type);
		switch (storageType){
			case OSS:
				return this.getObjectContentFromAli(bucketName, objectName);
			case AWS:
				return this.getObjectContentFromAws(bucketName, objectName);
			case LOCAL:
				return this.getObjectContentFromLocal(objectName);
		}
		return null;
	}

	/**
	 * 获取文件内容-阿里云
	 * @param bucketName
	 * @param objectName
	 * @return
	 */
	public String getObjectContentFromAli(String bucketName, String objectName){
		//创建oss客户端
		OSSClient ossClient = new OSSClient(point, key, secrey);
		InputStream objectContent = null;
		StringBuilder contentJson = new StringBuilder();
		try {
			// ossObject包含文件所在的存储空间名称、文件名称、文件元信息以及一个输入流。
			OSSObject ossObject = ossClient.getObject(bucketName, objectName);
			objectContent = ossObject.getObjectContent();
			try(BufferedReader reader = new BufferedReader(new InputStreamReader(objectContent))){
				while (true) {
					String line = reader.readLine();
					if (line == null) break;
					contentJson.append(line);
				}
			} catch (IOException e) {
				log.error("读取scene.json文件流失败", e);
			}
		}catch (Exception e){
			log.error("s3获取文件内容失败,key="+objectName, e);
		}finally {
			if(ossClient != null){
				ossClient.shutdown();
			}
		}

		return contentJson.toString();
	}

	/**
	 * 获取文件内容-阿里云
	 * @param objectName
	 * @return
	 */
	public boolean existOnAli(String bucket, String objectName){
		//创建oss客户端
		OSSClient ossClient = new OSSClient(point, key, secrey);
		// ossObject包含文件所在的存储空间名称、文件名称、文件元信息以及一个输入流。
		try{
			boolean exist = ossClient.doesObjectExist(bucket, objectName);
			return exist;
		}catch (Exception e){
			log.error("s4判断是否存在key异常,key=" + objectName, e);
		}finally {
			if(ossClient != null){
				ossClient.shutdown();
			}
		}
		return false;
	}

	/**
	 * 获取文件内容-亚马逊
	 * @param bucketName
	 * @param objectName
	 * @return
	 */
	public String getObjectContentFromAws(String bucketName, String objectName){

		try {
			/**
			 * 创建s3对象
			 */
			BasicAWSCredentials awsCreds = new BasicAWSCredentials(s3key, s3secrey);
			AmazonS3 s3 = AmazonS3ClientBuilder.standard()
				.withCredentials(new AWSStaticCredentialsProvider(awsCreds))
				.withRegion(Regions.EU_WEST_2)
				.build();

			GetObjectRequest request  = new GetObjectRequest(bucketName,objectName);
			S3Object object = s3.getObject(request);
			S3ObjectInputStream inputStream = object.getObjectContent();
			StringBuilder content = new StringBuilder();
			try(BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))){
				while (true) {
					String line = reader.readLine();
					if (line == null) break;
					content.append(line);
				}
			} catch (IOException e) {
				log.error("读取aws文件流失败", e);
			}
			return content.toString();
		} catch (Exception ase) {
			log.error("amazonS3下载文件异常 " + ase.getMessage(), ase);
		}
		return null;

	}

	/**
	 * 获取文件内容-亚马逊
	 * @param objectName
	 * @return
	 */
	public boolean existOnAws(String bucket, String objectName){

		BasicAWSCredentials awsCreds = new BasicAWSCredentials(s3key, s3secrey);
		AmazonS3 s3 = AmazonS3ClientBuilder.standard()
			.withCredentials(new AWSStaticCredentialsProvider(awsCreds))
			.withRegion(Regions.EU_WEST_2)
			.build();
		try {
			boolean exist = s3.doesObjectExist(bucket, objectName);
			return exist;
		}catch (Exception e){
			log.error("s4判断是否存在key异常,key=" + objectName, e);
		}finally {
			if(s3 != null){
				s3.shutdown();
			}
		}
		return false;
	}

	/**
	 * 判断key是否存在
	 * @param key
	 * @return
	 */
	public boolean existKey(String bucket, String key){
		StorageType storageType = StorageType.get(type);
		switch (storageType){
			case OSS:
				return this.existOnAli(bucket, key);
			case AWS:
				return this.existOnAws(bucket, key);
			default:
				return false;
		}
	}

	/**
	 * 获取文件内容-本地
	 * @param objectName
	 * @return
	 */
	public String getObjectContentFromLocal(String objectName){
		// TODO: 2022/1/21
		return null;
	}

	/**
	 * oss下载文件到本地
	 * @param objectName
	 * @param localPath
	 */
	public boolean download(String bucket, String objectName, String localPath){
		StorageType storageType = StorageType.get(this.type);
		switch (storageType){
			case OSS:
				return this.downFormAli(bucket, objectName, localPath);
			case AWS:
				return this.downFromS3(bucket, objectName, localPath);
		}
		return false;
	}

	/**
	 * 从阿里云oss下载文件到本地
	 * @param objectName 云端文件k地址
	 * @param localPath 本地文件地址
	 * @return
	 */
	public boolean downFormAli(String bucket, String objectName, String localPath){
		OSSClient ossClient = new OSSClient(point, key, secrey);
		try {
			com.aliyun.oss.model.GetObjectRequest request  = new com.aliyun.oss.model.GetObjectRequest(bucket,objectName);
			ossClient.getObject(request, new File(localPath));
			return true;
		}catch (Exception e){
			log.error("阿里云oss文件下载失败，key=" + objectName, e);
		}finally {
			if(ossClient != null){
				ossClient.shutdown();
			}
		}
		return false;
	}

	/**
	 * 从s3下载文件到本地
	 * @param objectName 云端文件k地址
	 * @param localPath 本地文件地址
	 * @return
	 */
	public boolean downFromS3(String bucket, String objectName, String localPath) {
		BasicAWSCredentials awsCreds = new BasicAWSCredentials(s3key, s3secrey);
		AmazonS3 s3 = AmazonS3ClientBuilder.standard()
			.withCredentials(new AWSStaticCredentialsProvider(awsCreds))
			.withRegion(Regions.EU_WEST_2)
			.build();
		try {
			GetObjectRequest request  = new GetObjectRequest(bucket,objectName);
			s3.getObject(request,new File(localPath));
			return true;
		} catch (Exception e) {
			log.error("amazonS3下载文件失败，key=" + objectName, e);
		}finally {
			if(s3 != null){
				s3.shutdown();
			}
		}
		return false;
	}

}
