AWS Download file - Lambda, S3
Problem
How to download file from S3 and send it over the HTTP to the client which make call for it?
Solution
Bellow you can find the code which works. It is written in Java because it is language I'm mostly using in my work. And after this snippet of code you will find the description what is done in this code. I would like to just mentioned that it is not the best solution. Nevertheless, it is the solution which work, and I hope it helps you to come up with solution for your case. In this post I will not explain how to upload .jar file to the lambda. I will assume that you know how to do it. If not you can find it in AWS Documentation, it is very simple, press one button, select jar, save.
public class DownloadFileHandler implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> { @Override public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent event, Context context) { String bucket = ""; // 2 try (InputStream input = new FileInputStream("./config/application.properties")) { Properties properties = new Properties(); properties.load(input); bucket = properties.getProperty("bucket"); } catch (IOException e) { e.printStackTrace(); } // 3 String fileName = event.getQueryStringParameters().get("fileName"); // 4 S3Presigner presigner = S3Presigner.builder().build(); GetObjectPresignRequest presignRequest = GetObjectPresignRequest .builder() .signatureDuration(Duration.ofMinutes(10)) .getObjectRequest(GetObjectRequest.builder().bucket(bucket).key(fileName).build()) .build(); PresignedGetObjectRequest presignedGetObjectRequest = presigner.presignGetObject(presignRequest); String presignedURL = presignedGetObjectRequest.url().toString(); // 5 Map<String, String> headers = new LinkedHashMap<>(); headers.put("Content-Type", "application/json"); headers.put("Location", presignedURL); // 6 APIGatewayProxyResponseEvent responseEvent = new APIGatewayProxyResponseEvent() .withHeaders(headers) .withStatusCode(302); return responseEvent; } }
In the code you can see comment with numbers. In here I will try to explain what is done in code below each comment.
#1 In here it is important to implements one of the interfaces which are provided by AWS-SDK. I choose RequestHandler<In, Out>
only because I am using it the most. It helps me to deal with request and response events. Like you can see in
this example it is very simple to get query parameter from the request. But more about that later.
#2 Under this number it is simply reading properties files where I have defined few configurations variable which I do not
want to include directly in the code. Like username, password, but what is more important for us bucket name.
#3 This code is very important. We are getting query parameter from the event request.
I think it is very crucial mention that I am not doing any check in here, so if for example
fileName will not exist the lambda
will not work and return something like { "message" : "Internal server error" }.
You should add some checks if fileName exists. But I want to keep this example very simple
and focus on what is important here.
Under this link
you can find APIGatewayProxyRequestEvent documentation. You can see there is a lot of
useful methods. One of them is getQueryStringParameters() which return Map<String, String>
which contain all parameters send to our lambda. For example if you send request like http://someurl.com/api?name=Joe&surname=Doe
this map will contains keys name and surname with they values.
That why is worth to check first if this map contains key which we expects.
Map<String, String> parameters = event.getQueryStringParameters(); if(parameters.contains("fileName")) // do something here if key exist
home