How to read a file in AWS Lambda Function written in Java ?
Solution 1
I have made following changes in my code and now its works perfect :
Majorly changed following two lines :
ClassLoader classLoader = getClass().getClassLoader();
File cityFile = new File(classLoader.getResource("City.db").getFile());
package com.lambda;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.LambdaLogger;
import com.amazonaws.services.lambda.runtime.RequestStreamHandler;
import java.io.*;
public class TestDetailsHandler implements RequestStreamHandler {
public void handleRequest(InputStream input,OutputStream output,Context context){
// Get Lambda Logger
LambdaLogger logger = context.getLogger();
// Receive the input from Inputstream throw exception if any
ClassLoader classLoader = getClass().getClassLoader();
File cityFile = new File(classLoader.getResource("City.db").getFile());
FileInputStream fis = null;
try {
fis = new FileInputStream(cityFile);
System.out.println("Total file size to read (in bytes) : "
+ fis.available());
int content;
while ((content = fis.read()) != -1) {
// convert to char and display it
System.out.print((char) content);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fis != null)
fis.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
Solution 2
This is how I did it, let's say this is how your project structure looks like -
And you want to read the file config.properties which is inside the project-dir/resources directory.
The code for reading the content of the file would be -
InputStream input = null;
try {
Path path = Paths.get(PropertyUtility.class.getResource("/").toURI());
// The path for config file in Lambda Instance -
String resourceLoc = path + "/resources/config.properties";
input = new FileInputStream(resourceLoc);
} catch(Exception e) {
// Do whatever
}
If you are following this project structure and using this code, then it will work in AWS Lambda.
PropertyUtility is just a utility class that I have created to read the contents of the config file. The PropertyUtility class looks like this -
As you can see in the above code, the path of the config file is different in the local system and in Lambda Instance.
In your local machine, PropertyUtility.class.getResource("/") points to bin, that is why you have to do path.getParent(), to point it to the project-directory which is HelloLambda in this example.
For the Lambda Instance, PropertyUtility.class.getResource("/") points directly to the project-directory.
Solution 3
If the file in located under resources directory, then the following solution should work:
String fileName = "resources/config.json";
Path path = Paths.get(this.getClass().getResource("/").toURI());
Path resourceLocation = path.resolve(fileName);
try(InputStream configStream = Files.newInputStream(resourceLocation)) {
//use your file stream as you need.
}
Here the most important part is "resources/config.json", it must not be "/resources/config.json", because the file location is /var/task/resources/config.json in lambda, I checked.
Hope this helps who still face problem in reading file in aws lambda.
Solution 4
If the file is located under resources folder, you can use it directly in lambda by using something like the following code:
final BufferedReader br = new BufferedReader(new FileReader("/flows/cancellation/MessageArray.json"));
I wanted to read a json file, you can have different use case, but the code works.
Comments
-
Sumit Arora about 4 years
I have written an AWS Lambda Handler as below :
package com.lambda; import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.LambdaLogger; import com.amazonaws.services.lambda.runtime.RequestStreamHandler; import java.io.*; public class TestDetailsHandler implements RequestStreamHandler { public void handleRequest(InputStream input,OutputStream output,Context context){ // Get Lambda Logger LambdaLogger logger = context.getLogger(); // Receive the input from Inputstream throw exception if any File starting = new File(System.getProperty("user.dir")); System.out.println("Source Location" + starting); File cityFile = new File(starting + "City.db"); FileInputStream fis = null; try { fis = new FileInputStream(cityFile); System.out.println("Total file size to read (in bytes) : " + fis.available()); int content; while ((content = fis.read()) != -1) { // convert to char and display it System.out.print((char) content); } } catch (IOException e) { e.printStackTrace(); } finally { try { if (fis != null) fis.close(); } catch (IOException ex) { ex.printStackTrace(); } } } }
Its read a file : City.db , available in resources folder, even I kept to everywhere see below :
But it showing following message on execution of this lambda function :
START RequestId: 5216ea47-fc43-11e5-96d5-83c1dcdad75d Version: $LATEST Source Location/ java.io.FileNotFoundException: /city.db (No such file or directory) at java.io.FileInputStream.open0(Native Method) at java.io.FileInputStream.open(FileInputStream.java:195) at java.io.FileInputStream.<init>(FileInputStream.java:138) at com.lambda.TestDetailsHandler.handleRequest(TestDetailsHandler.java:26) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:497) at lambdainternal.EventHandlerLoader$StreamMethodRequestHandler.handleRequest(EventHandlerLoader.java:511) at lambdainternal.EventHandlerLoader$2.call(EventHandlerLoader.java:972) at lambdainternal.AWSLambda.startRuntime(AWSLambda.java:231) at lambdainternal.AWSLambda.<clinit>(AWSLambda.java:59) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:348) at lambdainternal.LambdaRTEntry.main(LambdaRTEntry.java:93) END RequestId: 5216ea47-fc43-11e5-96d5-83c1dcdad75d REPORT RequestId: 5216ea47-fc43-11e5-96d5-83c1dcdad75d Duration: 58.02 ms Billed Duration: 100 ms Memory Size: 1024 MB Max Memory Used: 50 MB
Contents of the Pom.xml file :
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.lambda</groupId> <artifactId>testdetails</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <name>test-handler</name> <dependencies> <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-core</artifactId> <version>1.1.0</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>2.3</version> <configuration> <createDependencyReducedPom>false</createDependencyReducedPom> </configuration> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </project>
I have used various ways to keep file here and there , but at the end its not working. May you please let me know what is wrong here ?
However in my another project where I have kept xyz.properties file in resources folder and reading from a PropertyManager file, its working fine. When I tested it on my system its working fine, but on AWS Lambda function it doesn't work.
-
Prashant about 7 yearsUse getaresourceAsStream() instead. You don't need to convert it to a file which might not work in all cases.