How to read a file in AWS Lambda Function written

2020-05-27 11:01发布

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 :

enter image description here

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  

enter image description here

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.

4条回答
家丑人穷心不美
2楼-- · 2020-05-27 11:44

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.

查看更多
等我变得足够好
3楼-- · 2020-05-27 11:53

This is how I did it, let's say this is how your project structure looks like -

enter image description here

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 -

enter image description here

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.

查看更多
来,给爷笑一个
4楼-- · 2020-05-27 12:02

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();
            }
        }
    }

enter image description here

查看更多
三岁会撩人
5楼-- · 2020-05-27 12:07

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. enter image description here

查看更多
登录 后发表回答