Stirling-PDF icon indicating copy to clipboard operation
Stirling-PDF copied to clipboard

[Bug]: Merge PDFs with API call

Open hal-berto opened this issue 1 year ago • 4 comments

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.

hal-berto avatar Dec 19 '24 10:12 hal-berto

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 Authorization header 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

dosubot[bot] avatar Dec 19 '24 10:12 dosubot[bot]

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

Ludy87 avatar Dec 19 '24 12:12 Ludy87

Many thanks. The missing part was the "@" character before the file path. Now it's working properly

hal-berto avatar Dec 19 '24 15:12 hal-berto

S

SamehHanna10 avatar Dec 30 '24 08:12 SamehHanna10