Firstly, sorry for poor english.
I'm using s3 bucket. Because frontend(react) and backend(spring boot) are separated, I tried to make it possible to upload file directly from frontend using presigned url that AWS SDK provided.
How Can I set MetaData of S3 Bucket Objet?
Uploading using SDK from backend was simple. All I had to do is to add some code like below.
val objectMetadata = ObjectMetadata()
objectMetadata.contentDisposition = "attachment; filename=\"${urlEncodedOriginalFileName}\"; filename*=UTF-8'${urlEncodedOriginalFileName}'"
objectMetadata.contentLength = file.bytes.size.toLong()
But I'm struggling with adding Object MetaData using preSignedURL. What is the exact way to put Object MetaData to uploaded file(S3 Object)?
I tried like this way. But It didn't work.
package com.sunnyfactory.haeorum.controller.share
import com.amazonaws.HttpMethod
import com.amazonaws.services.s3.AmazonS3
import com.amazonaws.services.s3.Headers
import com.amazonaws.services.s3.model.CannedAccessControlList
import com.amazonaws.services.s3.model.GeneratePresignedUrlRequest
import com.amazonaws.services.s3.model.ResponseHeaderOverrides
import org.springframework.beans.factory.annotation.Value
import org.springframework.http.RequestEntity
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
import java.net.URL
import java.text.SimpleDateFormat
import java.util.*
@RestController
@RequestMapping("/api/attachment")
class AttachmentController (
private val amazonS3: AmazonS3
){
@Value("\${amazon.aws.s3.bucket-name}")
lateinit var bucketName: String
@GetMapping("/upload-pre-signed-url")
fun getUploadPreSignedUrl(): Map<String, String> {
val expiration = Date()
expiration.time = expiration.time + 1000 * 60 * 30
val uuid = UUID.randomUUID().toString().toLowerCase();
val year = SimpleDateFormat("YYYY").format(Date())
val date = SimpleDateFormat("MM-dd").format(Date())
val awsS3Key = "photo/${year}/${date}/${uuid}"
val generatedPresignedUrlRequest = GeneratePresignedUrlRequest(bucketName, awsS3Key)
.withMethod(HttpMethod.PUT)
.withExpiration(expiration)
generatedPresignedUrlRequest.addRequestParameter(
Headers.S3_CANNED_ACL,
CannedAccessControlList.PublicRead.toString()
)
generatedPresignedUrlRequest.addRequestParameter(
Headers.CONTENT_DISPOSITION,
"attachment; filename=\"abc.jpg\""
)
val responseHeader = ResponseHeaderOverrides()
responseHeader.withContentType("application/octet-stream")
responseHeader.withContentDisposition("attachment; filename=\"abc.jpg\"")
generatedPresignedUrlRequest.withResponseHeaders(responseHeader)
val preSignedUrl = amazonS3.generatePresignedUrl(
generatedPresignedUrlRequest
)
val returnValue = mutableMapOf<String, String>()
returnValue["preSignedUrl"] = preSignedUrl.toString()
returnValue["awsS3Key"] = awsS3Key
return returnValue
}
}
export const getUploadPresignedUrl = () => nonLoadingAxios.get(authUrl + '/upload-pre-signed-url');
export const uploadFileToAws = (preSignedUrl: string, file: File, renewUploadProgress?: (loaded:number, total: number)=>void, cancelToken?: CancelTokenSource) => {
const uriEncodedFileName = encodeURI(file.name)
return vanillaAxios.put(
preSignedUrl,
file,
{
headers: new Headers({
'Content-Type': 'image/*',
'Content-Disposition': 'attachment;' //It doesn't work.
}),
onUploadProgress: (progress) => {
if(renewUploadProgress){
renewUploadProgress(progress.loaded, progress.total)
}
},
cancelToken: cancelToken?.token
},
)
}