Parse multipart/form-data Body on AWS Lambda in Java

三世轮回 提交于 2020-12-25 09:52:51

问题


I am new to AWS Lambda and I am trying to implement a Lambda function that receives a POST request containing data encoded as multipart/form-data. The message is received through the API Gateway using Lambda Proxy integration and the body is encoded in Base64 when it arrives to the Lambda function. After decoding it manually, I see it contains a multipart body like the following:

-----WebKitFormBoundary3EZ0C3tbP2JpAmz4
Content-Disposition: form-data; name="param1"

value1
-----WebKitFormBoundary3EZ0C3tbP2JpAmz4
Content-Disposition: form-data; name="param2"

value2
------WebKitFormBoundary3EZ0C3tbP2JpAmz4
Content-Disposition: form-data; name="myfile"; filename="ivr.png"
Content-Type: image/png

PNG
... [binary stuff]
------WebKitFormBoundary3EZ0C3tbP2JpAmz4--

What I need is to parse this message in java 8 so I can access the individual parts. I managed to do it using the +javax.mail.Multipart+ object but it seems I cannot access the "name" property for the parts and as such I cannot distinguish between same type elements, e.g. "param1" and "param2". I believe this can be related to the fact that this Class is for parsing email messages... Is there another way to parse this multipart body inside the lambda function? This is the code I have to parse it (base64 is the string containing the body):

DataSource source = new ByteArrayDataSource(new ByteArrayInputStream(Base64.decodeBase64(base64)), "multipart/mixed");
MimeMultipart mp = new MimeMultipart(source);

I'd appreciate any help you can provide.


回答1:


Ok so this is definitely NOT the ideal solution but I was able to make this work.

Problem

There are actually many libraries out there to parse multipart form data. The actual problem is all libraries rely on javax.servlet package - most importantly HttpServletRequest class (and few more).

Since we can't access javax.servlet package classes in AWS Lambda environment, my solution is to fix that.


Solution

  1. Download the javax.servlet package from GitHub and add that to you your lambda function. See the image below - you can see that my class MultipartFormDataTest is within my package com... and I also have javax.servlet package within the same Java module.



  1. Once we do this, we can use one or more libraries that will do all the work for us. The best library I've found that will parse the file content is Delight FileUpload - https://mvnrepository.com/artifact/org.javadelight/delight-fileupload.

  2. Once that library is added, the method below getFilesFromMultipartFormData() will return ArrayList<File> where each item in the list represents a File that was sent in the request.

/**
 * @param context context
 * @param body this value taken from the `request.getBody()`
 * @param contentType this value is taken from `request.headers().get("Content-Type")`
 * @return List of File objects
 */
private List<File> getFilesFromMultipartFormData(Context context, String body, String contentType) {
    ArrayList<File> files = new ArrayList<>();
    List<FileItem> fileItems = FileUpload.parse(body.getBytes(StandardCharsets.UTF_8), contentType);

    for(FileItem fileItem : fileItems) {
        if(fileItem == null) {
            continue;
        }

        logger.log("fileItem name: " + fileItem.getName());
        logger.log("fileItem content-type: " + fileItem.getContentType());
        logger.log("fileItem size: " + fileItem.getSize());

        // Note: instead of storing it locally, you can also directly store it to S3 for example
        try {
            // I'm setting the extension to .png but you can look at the fileItem.getContentType()
            // to make sure it is an image vs. pdf vs. some other format
            File temp = File.createTempFile(fileItem.getName(), ".png");
            Files.copy(fileItem.getInputStream(), temp.toPath(), StandardCopyOption.REPLACE_EXISTING);
            files.add(temp);
        } catch (Exception e) {
            continue;
        }
    }

    return files;
}


来源:https://stackoverflow.com/questions/43875504/parse-multipart-form-data-body-on-aws-lambda-in-java

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!