[Bug]: Merge PDFs with API call
Installation Method
None
The Problem
Greetings, I'm trying to implement a call to StirlingPDF APIs to merge different PDF documents (I'm referring to API /general/merge-pdfs). I tried with the following cURL calls:
curl -X 'POST'
'https://stirlingpdf.io/api/v1/general/merge-pdfs'
-H 'accept: /'
-H 'Content-Type: multipart/form-data'
-F 'fileInput=path_to_file_1.pdf'
-F 'fileInput=path_to_file_2.pdf'
-F 'sortType=orderProvided'
-F 'removeCertSign=true'
and this variation:
curl -X 'POST'
'https://stirlingpdf.io/api/v1/general/merge-pdfs'
-H 'accept: /'
-H 'Content-Type: multipart/form-data'
-F 'fileInput[]=path_to_file_1.pdf'
-F 'fileInput[]=path_to_file_2.pdf'
-F 'sortType=orderProvided'
-F 'removeCertSign=true'
In both cases I receive an error:
"Bad Request","exception":"org.springframework.web.bind.MethodArgumentNotValidException","trace":"org.springframework.web.bind.MethodArgumentNotValidException: Validation failed for argument [0] in public org.springframework.http.ResponseEntity<byte[]> stirling.software.SPDF.controller.api.MergeController.mergePdfs(stirling.software.SPDF.model.api.general.MergePdfsRequest) throws java.io.IOException: [Field error in object 'mergePdfsRequest' on field 'fileInput': rejected value [Array]; codes [typeMismatch.mergePdfsRequest.fileInput,typeMismatch.fileInput,typeMismatch.[Lorg.springframework.web.multipart.MultipartFile;,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [mergePdfsRequest.fileInput,fileInput]; arguments []; default message [fileInput]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'org.springframework.web.multipart.MultipartFile[]' for property 'fileInput'; Cannot convert value of type 'java.lang.String' to required type 'org.springframework.web.multipart.MultipartFile' for property 'fileInput[0]': no matching editors or conversion strategy found]
I know for sure that the file path is correct, since I succesfully called other StirlingPDF APIs with the same path. Is there something wrong with my cURL?
Version of Stirling-PDF
0.36.4
Last Working Version of Stirling-PDF
No response
Page Where the Problem Occurred
No response
Docker Configuration
No response
Relevant Log Output
"Bad Request","exception":"org.springframework.web.bind.MethodArgumentNotValidException","trace":"org.springframework.web.bind.MethodArgumentNotValidException: Validation failed for argument [0] in public org.springframework.http.ResponseEntity<byte[]> stirling.software.SPDF.controller.api.MergeController.mergePdfs(stirling.software.SPDF.model.api.general.MergePdfsRequest) throws java.io.IOException: [Field error in object 'mergePdfsRequest' on field 'fileInput': rejected value [Array]; codes [typeMismatch.mergePdfsRequest.fileInput,typeMismatch.fileInput,typeMismatch.[Lorg.springframework.web.multipart.MultipartFile;,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [mergePdfsRequest.fileInput,fileInput]; arguments []; default message [fileInput]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'org.springframework.web.multipart.MultipartFile[]' for property 'fileInput'; Cannot convert value of type 'java.lang.String' to required type 'org.springframework.web.multipart.MultipartFile' for property 'fileInput[0]': no matching editors or conversion strategy found]] \\n\\tat org.springframework.web.method.annotation.ModelAttributeMethodProcessor.resolveArgument(ModelAttributeMethodProcessor.java:158)\\n\\tat org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:122)\\n\\tat org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:224)\\n\\tat org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:178)\\n\\tat org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:118)\\n\\tat org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:986)\\n\\tat org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:891)\\n\\tat org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)\\n\\tat org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1088)\\n\\tat org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:978)\\n\\tat org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014)\\n\\tat org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:914)\\n\\tat jakarta.servlet.http.HttpServlet.service(HttpServlet.java:547)\\n\\tat org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885)\\n\\tat jakarta.servlet.http.HttpServlet.service(HttpServlet.java:614)\\n\\tat org.eclipse.jetty.ee10.servlet.ServletHolder.handle(ServletHolder.java:736)\\n\\tat org.eclipse.jetty.ee10.servlet.ServletHandler$ChainEnd.doFilter(ServletHandler.java:1614)\\n\\tat org.eclipse.jetty.ee10.websocket.servlet.WebSocketUpgradeFilter.doFilter(WebSocketUpgradeFilter.java:195)\\n\\tat org.eclipse.jetty.ee10.servlet.FilterHolder.doFilter(FilterHolder.java:205)\\n\\tat org.eclipse.jetty.ee10.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1586)\\n\\tat stirling.software.SPDF.config.security.IPRateLimitingFilter.doFilter(IPRateLimitingFilter.java:62)\\n\\tat org.eclipse.jetty.ee10.servlet.FilterHolder.doFilter(FilterHolder.java:205)\\n\\tat org.eclipse.jetty.ee10.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1586)\\n\\tat stirling.software.SPDF.config.security.UserBasedRateLimitingFilter.doFilterInternal(UserBasedRateLimitingFilter.java:48)\\n\\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)\\n\\tat org.eclipse.jetty.ee10.servlet.FilterHolder.doFilter(FilterHolder.java:205)\\n\\tat org.eclipse.jetty.ee10.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1586)\\n\\tat stirling.software.SPDF.config.security.UserAuthenticationFilter.doFilterInternal(UserAuthenticationFilter.java:53)\\n\\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)\\n\\tat org.eclipse.jetty.ee10.servlet.FilterHolder.doFilter(FilterHolder.java:205)\\n\\tat org.eclipse.jetty.ee10.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1586)\\n\\tat stirling.software.SPDF.config.security.FirstLoginFilter.doFilterInternal(FirstLoginFilter.java:74)\\n\\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)\\n\\tat org.eclipse.jetty.ee10.servlet.FilterHolder.doFilter(FilterHolder.java:205)\\n\\tat org.eclipse.jetty.ee10.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1586)\\n\\tat stirling.software.SPDF.config.MetricsFilter.doFilterInternal(MetricsFilter.java:48)\\n\\tat org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)\\n\\tat org.eclipse.jetty.ee10.servlet.FilterHolder.doFilter(FilterHolder.java:205)\\n\\tat org.eclipse.jetty.ee10.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1586)\\n\\tat org.springframework.web.filter.CompositeFilter$VirtualFilterChain.doFilter(CompositeFilter.java:108)\\n\\tat org.springframework.security.web.FilterChainProxy.lambda$doFilterInternal$3(FilterChainProxy.java:231)\\n\\tat org.springframework.security.web.ObservationFilterChainDecorator$FilterObservation$SimpleFilterObservation.lambda$wrap$1(ObservationFilterChainDecorator.java:479)\\n\\tat org.springframework.security.web.ObservationFilterChainDecorator$AroundFilterObservation$SimpleAroundFilterObservation.lambda$wrap$1(ObservationFilterChainDecorator.java:340)\\n\\tat org.springframework.security.web.ObservationFilterChainDecorator.lambda$wrapSecured$0(ObservationFilterChainDecorator.java:82)\\n\\tat org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:128)\\n\\tat org.springframework.security.web.access.intercept.AuthorizationFilter.doFilter(AuthorizationFilter.java:101)\\n\\tat org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240)\\n\\tat org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227)\\n\\tat org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137)\\n\\tat org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:126)\\n\\tat org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:120)\\n\\tat org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240)\\n\\tat org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227)\\n\\tat org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137)\\n\\tat org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:100)\\n\\tat org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.wrapFilter(ObservationFilterChainDecorator.java:240)\\n\\tat org.springframework.security.web.ObservationFilterChainDecorator$ObservationFilter.doFilter(ObservationFilterChainDecorator.java:227)\\n\\tat org.springframework.security.web.ObservationFilterChainDecorator$VirtualFilterChain.doFilter(ObservationFilterChainDecorator.java:137)\\n\\tat org.springframework.security.web.servletapi.SecurityContextHolderAware
Additional Information
No response
Browsers Affected
No response
No Duplicate of the Issue
- [X] I have verified that there are no existing issues raised related to my problem.
Hey @hal-berto! I'm here to help you with any bugs, questions, or contributions. Let's work together to resolve this issue.
The error you're encountering suggests that the fileInput field is not being correctly interpreted as an array of MultipartFile objects. In your cURL request, you should ensure that each file is specified correctly as a file upload. Here's how you can structure your cURL command to properly send multiple files:
curl -X POST \
'https://stirlingpdf.io/api/v1/general/merge-pdfs' \
-H 'accept: */*' \
-H 'Content-Type: multipart/form-data' \
-F 'fileInput=@path_to_file_1.pdf' \
-F 'fileInput=@path_to_file_2.pdf' \
-F 'sortType=orderProvided' \
-F 'isRemoveCertSign=true' \
-H 'Authorization: Bearer YOUR_API_KEY'
Key points to note:
- Use
@before the file path to indicate that the file should be uploaded. - Ensure that you include the
Authorizationheader with a valid API key, as the StirlingPDF API requires authentication [1].
Make sure to replace YOUR_API_KEY with your actual API key. This should help resolve the issue with the fileInput field not being recognized correctly.
To continue talking to Dosu, mention @dosu.
Help Dosu learn! Give it feedback: Great Response | Irrelevant Answer | Incorrect Sources | Too Verbose | Hallucination | Other
Hi @hal-berto try this:
windows prompt
curl -X POST "http://127.0.0.1:8080/api/v1/general/merge-pdfs" ^
-H "accept: */*" ^
-H "Content-Type: multipart/form-data" ^
-F "fileInput=@path_to_file_1.pdf" ^
-F "fileInput=@path_to_file_2.pdf" ^
-F "sortType=orderProvided" ^
-F "removeCertSign=false" ^
--output path_to_file_3.pdf
linux terminal
curl -X POST "http://127.0.0.1:8080/api/v1/general/merge-pdfs" \
-H "accept: */*" \
-H "Content-Type: multipart/form-data" \
-F "fileInput=@path_to_file_1.pdf" \
-F "fileInput=@path_to_file_2.pdf" \
-F "sortType=orderProvided" \
-F "removeCertSign=false" \
--output @path_to_file_3.pdf
Many thanks. The missing part was the "@" character before the file path. Now it's working properly
S