一般做图片上传的的业务时我们接收的都是 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
这样可以啦