<template>
	<div class="uploadBox"></div>
</template>

<script>
import "../../../../../../common/aws-sdk-2.235.1.min.js";
export default {
	props:{
		index:{
			type:String,
			default:"0"
		},
	},
	data() {
		return {
			bucket: "", //aws上传接口
			bucketname: "ccrb", //桶
			uploadid: "",
			partsize: 10 * 1024 * 1024, //10MB  分片
			filestate: {
				status: "", //有 error（直接报错） 和 fail（上传的时候报错） 和 success（上传成功） 和 processing（上传中）
				percent: "", //（0-100的进度）
			},
			file: null,
			flag:true,
		};
	},
	watch: {
		filestate: {
			handler(newValue) {
				this.$emit("progressUpdate", {index:this.index,...newValue});
			},
			immediate: true,
			deep: true,
		},
	},
	methods: {
		//--------------------------分断上传保证稳定性
		//初始化上传
		// async init(){
		// 	const credentials = {
		// 	    accessKeyId: "AKIATLPEDU37QV5CHLMH",
		// 	    secretAccessKey: "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",
		// 	}; //秘钥形式的登录上传
		// 	window.AWS.config.update(credentials);
		// 	window.AWS.config.region = "cn-northwest-1"; //设置区域
		// 	//桶的设置
		// 	bucket = new window.AWS.S3({
		// 	    params: {
		// 	        Bucket: this.bucketname
		// 	    }
		// 	});
		// 	return bucket;
		// },
		// 初始化上传入口
		async initMultipartUpload(key, file) {
			console.log(file)
			const params = {
				Bucket: this.bucketname,
				Key: key,
				ContentType: file.type,
				ACL: "public-read",
			};
			//创建一个续传通道
			const data = await this.bucket.createMultipartUpload(params).promise();
			return data.UploadId;
		},
		// 上传文件的某一部分
		async uploadPart(file, keyname, uploadid, pn, start, end) {
			//key可以设置为桶的相对路径，Body为文件， ACL最好要设置
			if(!this.flag)return;
			var params = {
				Bucket: this.bucketname,
				Key: keyname,
				// ContentType: file.type,
				PartNumber: pn,
				UploadId: uploadid,
				Body: file.slice(start, end),
				// "Access-Control-Allow-Credentials": "*",
				// ACL: "public-read",
			};
			const result = await this.bucket.uploadPart(params).promise();
			return { ETag: result.ETag, PartNumber: pn };
		},
		//完成分块上传
		async completeMultipartUpload(parts, keyname, uploadid) {
			if(!this.flag)return;
			const params = {
				Bucket: this.bucketname,
				Key: keyname,
				MultipartUpload: { Parts: parts },
				UploadId: uploadid,
			};
			return await this.bucket.completeMultipartUpload(params).promise();
		},
		async abortMultipartUpload(key, uploadid) {
			const params = {
				Bucket: this.bucketname,
				Key: key,
				UploadId: uploadid,
			};
			let data = await this.bucket.abortMultipartUpload(params).promise();
			this.$emit("delUpload",{index:this.index})
			
		},
		//--------------------------------下面支持断点续传

		//初始化亚马逊参数
		async init() {
			//秘钥形式的登录上传
			const credentials = {
				accessKeyId: "AKIATLPEDU37QV5CHLMH",
				secretAccessKey: "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",
				region: "cn-northwest-1",
			};
			window.AWS.config.update(credentials);
			// window.AWS.config.region = "cn-northwest-1"; //设置区域
			//桶的设置
			this.bucket = new window.AWS.S3({
				params: {
					Bucket: this.bucketname,
				},
			});
			return this.bucket;
		},

		//获取当前文件是否有已上传断点信息
		async getawscheckpoint(key) {
			let partsinfo;
			try {
				const result = await this.bucket
					.listMultipartUploads({ Bucket: this.bucketname, Prefix: key })
					.promise();
				//获取具体分片信息
				if (result.Uploads.length) {
					this.uploadid = result.Uploads[result.Uploads.length - 1].UploadId;
					partsinfo = await this.bucket
						.listParts({
							Bucket: this.bucketname,
							Key: key,
							UploadId: this.uploadid,
						})
						.promise();
				}
			} catch (err) {
				console.log(err);
			}
			return { uploadid: this.uploadid, partsinfo };
		},

		//分段上传
		async awsuploadpart(filestate, file, uploadid, parts, key) {
			var partarr = []; //已完成的数组
			//已完成的分片,转化成提交格式
			const completeparts = parts.map((_) => {
				partarr.push(_.PartNumber);
				return { PartNumber: _.PartNumber, ETag: _.ETag };
			});
			// 分块上传文件
			// parts = [];
			let uploadpart;
			let start = 0;
			let end = 0;
			let len = Math.ceil(file.size / this.partsize); //循环的长度
			if (partarr.length) {
				this.filestate.status = "processing";
				this.filestate.percent = parseInt((completeparts.length * 100) / len);
			}
			//循环上传
			for (let i = 0; i < len; i++) {
				if(!this.flag)break;
				start = i * this.partsize;
				end = (i + 1) * this.partsize;
				if (!partarr.includes(i+1)) {

					uploadpart = await this.uploadPart(
						file,
						key,
						uploadid,
						i + 1,
						start,
						end
					);
					if (uploadpart.ETag != null) {
						completeparts.push(uploadpart);
						partarr.push(uploadpart.PartNumber);
						this.filestate.status = "processing";
						this.filestate.percent = parseInt(
							(completeparts.length * 100) / len
						);
					} else {
						this.filestate.status = "fail";
						this.stopUpload();
						return;
					}
				}
			}
			//提交上传成功信息
			if(this.flag){
					let data = await this.completeMultipartUpload(
					completeparts,
					key,
					uploadid
				);
				this.filestate.status = "success";
				return data;
			}
		},

		//上传的接口
		async awsupload({ file = this.file, keyName, folderName }) {
			console.log('successsuccesssuccesssuccesssuccesssuccesssuccesssuccesssuccesssuccesssuccess')
			if (!file) return this.$message.error("请上传文件");
			this.init(); //初始化桶
			// const key = (folderid || uuidv4()) + "/" + file.name; //需要上传的文件名
			let key = "";
			if (keyName) {
				key = keyName;
			} else {
				if (folderName) {
					key = `${folderName}/${file.name}`;
				} else {
					key = `default/${file.name.split(".")[0] +
							new Date().getTime() +
							"." +
							file.name.split(".")[file.name.split(".").length - 1]}`;
				}
			}
			console.log(key);
			// key = key.replace(/\s/g, "");
			// key = encodeURIComponent(key);
			this.filestate = {
				percent: 0,
				status: "start",
			};
			this.filestate.percent = 0;
			this.filestate.status = "start";
			this.file = file;
			//上传的参数
			var params = {
				Bucket: this.bucketname,
				Key: key,
			};
			this.flag = true;
			//设置桶上传文件
			try {
				//检查文件是否已上传
				this.bucket.headObject(params, async (err, data) => {
					// 没有上传成功，head方法会返回失败
					if (err) {
						//检查是否部分上传
						const { uploadid, partsinfo } = await this.getawscheckpoint(
							key,
							this.bucket
						);
						//如果已经部分存在，那么直接在节点续传
						if (uploadid) {
							//断点续传
							this.$emit("startUpload", { index:this.index,key, uploadid });
							this.filestate.key = key;
							this.filestate.uploadid = uploadid;
							this.flag = true;
							let data = await this.awsuploadpart(
								this.filestate,
								file,
								uploadid,
								partsinfo.Parts,
								key
							);
							if(this.flag || this.filestate.percent==100)return this.$emit("success", {index:this.index, data, key, uploadid });
							// return {data,key,uploadid}
						}
						//不存在，上传新的
						else {
							const uploadid = await this.initMultipartUpload(key, file); //初始化文件上传
							this.$emit("startUpload", { index:this.index,key, uploadid });
							this.filestate.key = key;
							this.filestate.uploadid = uploadid;
							this.flag = true;
							let data = await this.awsuploadpart(
								this.filestate,
								file,
								uploadid,
								[],
								key
							);
							if(this.flag || this.filestate.percent==100)return this.$emit("success", {index:this.index, data, key, uploadid });
							// return {data,key,uploadid}
						}
					}
					//如果已经上传成功了，那么直接返回状态百分百
					else if (data) {
						//data存在，上传成功
						this.filestate.percent = 100;
						this.filestate.status = "success";
						let url = `https://ccrb.s3.cn-northwest-1.amazonaws.com.cn/${key}`
						this.file = null;
						if(this.flag)return this.$emit("success", { index:this.index,data:{
							Key:key,
							Location:url,
							ETag:data.ETag,
							size:data.ContentLength,
							ServerSideEncryption:data.ServerSideEncryption,
							Bucket:this.bucketname
							} });
						// return {data,key,uploadid}
					}
				});
			} catch (err) {
				this.filestate.status = "error";
				this.stopUpload();
				console.log(err);
			}
		},
		// 停止上传
		stopUpload(){
			this.filestate.status = "stop";
			this.flag = false;
		}
	},
	mounted() {
		this.bucket = "";
		this.file = null;
	},
};
</script>

<style scoped>
.uploadBox {
	display: none;
}
</style>
