You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I should get all files with same fieldname sent in request mapped as a list in rightFile
Actual behavior
I am only getting the last file mapped as a list of 1 MultipartFile in rightFile
Steps to reproduce
1.- create a SAM project with a Java Lambda that has enabled multipart form data in BinaryMediaTypes
template.yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: Example XlsComparator API written with SpringBoot with the aws-serverless-java-container library
Globals:
Api:
# API Gateway regional endpoints
EndpointConfiguration: REGIONAL
# Configure API to accept multipart form data
BinaryMediaTypes:
- "multipart~1form-data"
Cors:
AllowHeaders: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'"
AllowMethods: "'GET,POST,OPTIONS'"
AllowOrigin: "'*'"
2.- Create a Rest Controller in Spring with a POST Method with the following signature
@PostMapping("/compare")
public List compare( @RequestParam("leftFile") MultipartFile leftFile, @RequestParam("rightFile") List rightFile) {
...
}
3.- Set the library aws-serverless-java-container and configure it in the project to make the Lambda Integration with our Spring Boot Project, here is an example of StreamLambdaHandler.java used.
public class StreamLambdaHandler implements RequestHandler<AwsProxyRequest, AwsProxyResponse> {
private static SpringBootLambdaContainerHandler<AwsProxyRequest, AwsProxyResponse> handler;
static {
try {
handler = SpringBootLambdaContainerHandler.getAwsProxyHandler(ComparexcelApplication.class);
} catch (ContainerInitializationException e) {
e.printStackTrace();
throw new RuntimeException("Could not initialize Spring Boot application", e);
}
}
4.- Test the method by sending as form data only 1 file in field "leftFile" and 2 Files in field "righFile", you will se that in spring controller we will get only 2 files: 1 for leftFile and 1 for rightFile.
Full log output
There are no errors in Logs but still not getting all Files sent in request in the controller, I believe the issue is in AwsHttpServletRequest.java in this method:
@SuppressFBWarnings({"FILE_UPLOAD_FILENAME", "WEAK_FILENAMEUTILS"})
protected Map<String, Part> getMultipartFormParametersMap() {
if (multipartFormParameters != null) {
return multipartFormParameters;
}
if (!JakartaServletFileUpload.isMultipartContent(this)) { // isMultipartContent also checks the content type
multipartFormParameters = new HashMap<>();
return multipartFormParameters;
}
Timer.start("SERVLET_REQUEST_GET_MULTIPART_PARAMS");
multipartFormParameters = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
JakartaServletFileUpload upload = new JakartaServletFileUpload(DiskFileItemFactory.builder().get());
try {
**//Note: here we get the 3 items which is correct**
List<FileItem> items = upload.parseRequest(this);
for (FileItem item : items) {
String fileName = FilenameUtils.getName(item.getName());
AwsProxyRequestPart newPart = new AwsProxyRequestPart(item.get());
newPart.setName(item.getFieldName());
newPart.setSubmittedFileName(fileName);
newPart.setContentType(item.getContentType());
newPart.setSize(item.getSize());
item.getHeaders().getHeaderNames().forEachRemaining(h -> {
newPart.addHeader(h, item.getHeaders().getHeader(h));
});
**//ISSUE: the problem is here when there are two items with the same fieldName we lose the list of items because map is updated with a newPart instead of adding it to a List of newParts ?**
multipartFormParameters.put(item.getFieldName(), newPart);
}
} catch (FileUploadException e) {
Timer.stop("SERVLET_REQUEST_GET_MULTIPART_PARAMS");
log.error("Could not read multipart upload file", e);
}
Timer.stop("SERVLET_REQUEST_GET_MULTIPART_PARAMS");
return multipartFormParameters;
}
logs
The text was updated successfully, but these errors were encountered:
Thanks @mbfreder please let me know if you neet something more to reproduce the error, as I stated I believe the problem is in AwsHttpServletRequest.java int the method "getMultipartFormParametersMap" the result is a: "Map<String, Part>" but I think it should be a: Map< String, List<Part> >
Hi @LuisTDev. Sorry for the delay. I just realized I wrote the comment last week and forgot to click "Comment". I did reproduce the issue, and you're right about where the problem is. I'll find some time to fix it next week. Thanks
To help us debug your issue fill in the basic information below using the options provided
Serverless Java Container version:
2.0.0-M2
Implementations:
Spring Boot 3
Framework version:
SpringBoot 3.1.2
Frontend service:
REST API
Deployment method:
SAM, Serverless Framework
Scenario
I am trying to process this Spring Controller method where in "rightFile" I am expecting an Array of files with the same fieldName
@PostMapping("/compare") public List<ProcessedRow> compare( @RequestParam("leftFile") MultipartFile leftFile, @RequestParam("rightFile") List<MultipartFile> rightFile) { ... }
Expected behavior
I should get all files with same fieldname sent in request mapped as a list in rightFile
Actual behavior
I am only getting the last file mapped as a list of 1 MultipartFile in rightFile
Steps to reproduce
1.- create a SAM project with a Java Lambda that has enabled multipart form data in BinaryMediaTypes
template.yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: Example XlsComparator API written with SpringBoot with the aws-serverless-java-container library
Globals:
Api:
# API Gateway regional endpoints
EndpointConfiguration: REGIONAL
# Configure API to accept multipart form data
BinaryMediaTypes:
- "multipart~1form-data"
Cors:
AllowHeaders: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'"
AllowMethods: "'GET,POST,OPTIONS'"
AllowOrigin: "'*'"
Resources:
XlsComparatorFunction:
Type: AWS::Serverless::Function
Properties:
Handler: com.lthome.comparexcel.StreamLambdaHandler::handleRequest
Runtime: java17
CodeUri: .
MemorySize: 1512
Policies:
- AWSLambdaBasicExecutionRole
Timeout: 60
SnapStart:
ApplyOn: PublishedVersions
Events:
ApiEvent:
Type: Api
Properties:
Path: /compare
Method: post
2.- Create a Rest Controller in Spring with a POST Method with the following signature
@PostMapping("/compare")
public List compare(
@RequestParam("leftFile") MultipartFile leftFile,
@RequestParam("rightFile") List rightFile) {
...
}
3.- Set the library aws-serverless-java-container and configure it in the project to make the Lambda Integration with our Spring Boot Project, here is an example of StreamLambdaHandler.java used.
public class StreamLambdaHandler implements RequestHandler<AwsProxyRequest, AwsProxyResponse> {
private static SpringBootLambdaContainerHandler<AwsProxyRequest, AwsProxyResponse> handler;
static {
try {
handler = SpringBootLambdaContainerHandler.getAwsProxyHandler(ComparexcelApplication.class);
} catch (ContainerInitializationException e) {
e.printStackTrace();
throw new RuntimeException("Could not initialize Spring Boot application", e);
}
}
@OverRide
public AwsProxyResponse handleRequest(AwsProxyRequest input, Context context) {
AwsProxyResponse response = null;
response = handler.proxy(input, context);
// Set CORS Headers
response
.getMultiValueHeaders()
.put("Access-Control-Allow-Methods", List.of("GET", "POST", "OPTIONS"));
response
.getMultiValueHeaders()
.put(
"Access-Control-Allow-Headers",
List.of(
"Content-Type",
"X-Amz-Date",
"Authorization",
"X-Api-Key",
"X-Amz-Security-Token"));
response.getMultiValueHeaders().put("Access-Control-Allow-Origin", List.of("*"));
return response;
}
}
4.- Test the method by sending as form data only 1 file in field "leftFile" and 2 Files in field "righFile", you will se that in spring controller we will get only 2 files: 1 for leftFile and 1 for rightFile.
Full log output
There are no errors in Logs but still not getting all Files sent in request in the controller, I believe the issue is in AwsHttpServletRequest.java in this method:
@SuppressFBWarnings({"FILE_UPLOAD_FILENAME", "WEAK_FILENAMEUTILS"})
protected Map<String, Part> getMultipartFormParametersMap() {
if (multipartFormParameters != null) {
return multipartFormParameters;
}
if (!JakartaServletFileUpload.isMultipartContent(this)) { // isMultipartContent also checks the content type
multipartFormParameters = new HashMap<>();
return multipartFormParameters;
}
Timer.start("SERVLET_REQUEST_GET_MULTIPART_PARAMS");
multipartFormParameters = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
The text was updated successfully, but these errors were encountered: