I have set up AWS S3 bucket and I'm able to upload files there using Vapor 3 and Postman. I can also get files using Vapor 3 and Postman but I have a hard time to get and actually display files(png -images) on my browser (I'm using leaf).
So how can I display image files on the view? I'm new with HTML, AWS S3 and Vapor.
I'm using:
I followed this tutorial to set up everything (except the get request and the bucket policies): https://fivedottwelve.com/blog/using-amazon-s3-with-vapor/
Here are my Vapor code:
/// GET reguest
func preparePresignedImageUrl(request: Request) throws -> String {
let baseUrl = awsConfig.url
let imagePath = awsConfig.imagePath
let fileName = "x.png"
guard var url = URL(string: baseUrl) else {
throw Abort(.internalServerError)
}
url.appendPathComponent(imagePath)
url.appendPathComponent(fileName)
print("url is \(url)")
let headers = ["x-amz-acl" : "public-read"]
let s3 = try request.makeS3Signer()
let result = try s3.presignedURL(for: .GET, url: url, expiration: Expiration.hour, headers: headers)
/// Retrieve file data from S3
guard let presignedUrl = result?.absoluteString else {
throw Abort(.internalServerError)
}
return presignedUrl
}
The route:
// GET request
group.get("aws", "image", use: preparePresignedImageUrl)
And in the Postman when I make a GET request to that presignedURL
it gives me a status code 200OK.
My showImage.leaf
file:
#set("content") {
<h1>#(title)</h1>
// Here some html to get the image path and display the image?
<img>
}
#embed("base")
So I am going to assume that you have a perfectly good URL to the image.
Let's start by creating a route at GET /image
:
routes.get("image", use: image)
func image(_ request: Request) -> EventLoopFuture<View> {
}
To properly render the Leaf view, we will need a context that contains the data for the Leaf variables. It will look something like this:
struct ImageContext: Encodable {
let title: String
let imageURL: String
}
We also need to edit your leaf file so it will use the properties in the context:
#set("content") {
<h1>#(title)</h1>
<img src="#(imageURL)">
}
#embed("base")
Now we can render the leaf file with out new context and return the resulting view from the route handler. Here is what the implementation of the image
route handler will look like:
func image(_ request: Request) -> EventLoopFuture<View> {
let context = ImageContext(title: "Image", imageURL: preparePresignedImageUrl(request: request)
return try request.view().make("showImage", context)
}
Now you should be able to access localhost:8080/image
from your browser and the image will be there!