s3 实现图片上传并返回图片路径

一般做图片上传的的业务时我们接收的都是 MultipartFile 类型的文件 但是s3提供的图片上传只支持file 类型的文件上传,所以需要我先把 MultipartFile 转换为 file

	/**
	 * MultipartFile 转换为file
	 * 
	 * @param file
	 * @return
	 */
	public File toFile(MultipartFile file) {
		File toFile = new File(StringConstant.STATIC_NULL);
		if (file.equals(StringConstant.STATIC_NULL) || file.getSize() <= 0) {
			file = null;
		} else {
			InputStream ins = null;

			try {
				ins = file.getInputStream();
				toFile = new File(file.getOriginalFilename());
				inputStreamToFile(ins, toFile);
				ins.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

		return toFile;
	}

	/**
	 * 流转换为file
	 * 
	 *
	 * @param ins
	 * @param file
	 */
	public static void inputStreamToFile(InputStream ins, File file) {
		try {
			OutputStream os = new FileOutputStream(file);
			int bytesRead = 0;
			byte[] buffer = new byte[8192];
			while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) {
				os.write(buffer, 0, bytesRead);
			}
			os.close();
			ins.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

将文件类型转换后就需要将文件上传到s3

/**
	 * 上传文件到s3
	 * 
	 * 
	 * @param file
	 * @param key
	 * @param bukectName
	 * @param region
	 * @return
	 * @throws IOException
	 */
	public void uploadToS3(File file, String key, String bukectName,
			Regions region) throws IOException {

		long contentLength = file.length();
		long partSize = 5 * 1024 * 1024;
		try {
			AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
					.withRegion(region)
					.withCredentials(new ProfileCredentialsProvider()).build();

			List partETags = new ArrayList();

			// Initiate the multipart upload.
			InitiateMultipartUploadRequest initRequest = new InitiateMultipartUploadRequest(
					bukectName, key);
			InitiateMultipartUploadResult initResponse = s3Client
					.initiateMultipartUpload(initRequest);

			// Upload the file parts.
			long filePosition = 0;
			for (int i = 1; filePosition < contentLength; i++) {
				// Because the last part could be less than 5 MB, adjust the
				// part size as needed.
				partSize = Math.min(partSize, (contentLength - filePosition));

				// Create the request to upload a part.
				UploadPartRequest uploadRequest = new UploadPartRequest()
						.withBucketName(bukectName).withKey(key)
						.withUploadId(initResponse.getUploadId())
						.withPartNumber(i).withFileOffset(filePosition)
						.withFile(file).withPartSize(partSize);

				// Upload the part and add the response's ETag to our list.
				UploadPartResult uploadResult = s3Client
						.uploadPart(uploadRequest);
				partETags.add(uploadResult.getPartETag());

				filePosition += partSize;
			}

			// Complete the multipart upload.
			CompleteMultipartUploadRequest compRequest = new CompleteMultipartUploadRequest(
					bukectName, key, initResponse.getUploadId(), partETags);
			s3Client.completeMultipartUpload(compRequest);

		} catch (AmazonServiceException e1) {
			e1.printStackTrace();
		} catch (SdkClientException e) {
			e.printStackTrace();
		}
	}

到这为止我们就的图片就上传到 S3 啦

注意:上面的方法的参数的含义如下:

     file:就是要上传的文件

    key:就是文件的唯一标识(注意不要重复 ,如果重复会覆盖之前上传的文件)

    bukectName:就是存储桶的名称

   region:就是地区例如:Regions.US_WEST_2

但是在实际的项目中我们还需要获取到上传图片的路径进行回显,就需要执行下面的方法

	/**
	 * 生成预签名对象 URL
	 * 
	 * @author chendai
	 * @param clientRegion
	 * @param bucketName
	 * @param objectKey
	 * @return
	 */
	public String getSignatureUrl(String clientRegion, String bucketName,
			String objectKey) {
		String url = StringConstant.STATIC_NULL;

		try {
			AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
					.withRegion(clientRegion)
					.withCredentials(new ProfileCredentialsProvider()).build();

			// Set the presigned URL to expire after one hour.
			java.util.Date expiration = new java.util.Date();
			long expTimeMillis = expiration.getTime();
			// expTimeMillis += 1000 * 60 * 8640;
			long timeOut = Long.valueOf(AwsConfig.getTimeOut()).longValue();
			// expTimeMillis += 604800000;
			expTimeMillis += timeOut;
			expiration.setTime(expTimeMillis);

			// Generate the presigned URL.
			System.out.println("Generating pre-signed URL.");
			GeneratePresignedUrlRequest generatePresignedUrlRequest = new GeneratePresignedUrlRequest(
					bucketName, objectKey).withMethod(HttpMethod.GET)
					.withExpiration(expiration);
			URL fileUrl = s3Client
					.generatePresignedUrl(generatePresignedUrlRequest);

			System.out.println("Pre-Signed URL: " + fileUrl.toString());
			url = fileUrl.toString();
		} catch (AmazonServiceException e) {
			// The call was transmitted successfully, but Amazon S3 couldn't
			// process
			// it, so it returned an error response.
			e.printStackTrace();
		} catch (SdkClientException e) {
			// Amazon S3 couldn't be contacted for a response, or the client
			// couldn't parse the response from Amazon S3.
			e.printStackTrace();
		}
		return url;
	}

上面的方法生成的路径是这样的:

 https://dstech.s3.us-west-2.amazonaws.com/30212720904a4f0fbf48728453d01d10.jpg?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20190418T061044Z&X-Amz-SignedHeaders=host&X-Amz-Expires=604799&X-Amz-Credential=AKIA3CZHSC3GKUFCESSR%2F20190418%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Signature=07c46d4359a3568062aeeead185da80ca70bf67ec0b7201b7eb5e82aebddc231

红色的字代表的是它的签名 ,如果没有签名无法进行访问

签名的有效期是可以设置的但是允许设置的最长的时间为7天

至于怎么避开它的签名访问 我现在还不知道,如果有知道的可以联系我。

当然啦 还不能忘记引依赖,他们需要的依赖如下:

		
			org.apache.poi
			poi-ooxml
			3.11
		
		
			com.amazonaws
			aws-java-sdk-s3
			1.11.534
		
		
			software.amazon.awssdk
			ec2
			2.5.25
		
		
			software.amazon.awssdk
			s3
			2.5.25
		

这样可以啦

 

 

 

你可能感兴趣的:(亚马逊)