swagger-codegen-generators
swagger-codegen-generators copied to clipboard
[Spring] Support MultiPartFile for file uploads
Somewhat similar to https://github.com/swagger-api/swagger-codegen-generators/issues/150 but for Spring specifically.
When using the Spring profile and a multipart service definition, I would expect to be able to influence the generated api Controller stub to use Spring's org.springframework.web.multipart.MultiPartFile.
The options I've tried and result:
- type: string, format: binary maps to a byte[]
- type: file, format: binary maps to a
org.springframework.core.io.Resource
(I would expect this to use MultiPartFile instead)
As an alternative, I extended the SpringCodegen and registered my own typeMapping.
typeMapping.put{"multiPartFile","MultiPartFile");
importMapping.put("MultiPartFile", "org.springframework.web.multipart.MultiPartFile");
With this I was able to get a controller stub generated using the MultiPartFile and support uploads. I'm pretty new to this product so I'm not sure if this is a best practice or not.
@lion7 - given your experience and solution for #150 I'd be curious to get your perspective on the Spring flavor for the same use case.
@jglynn I submitted a pull request (actually 2 different ways of solving this) that should fix this issue.
A long story short: the binary
type is not interpreted correctly which causes the MultiPartFile
class to not be used. The code is actually there but due to this bug it is ignored.
The PR's are https://github.com/swagger-api/swagger-codegen-generators/pull/184 and https://github.com/swagger-api/swagger-codegen-generators/pull/185
Thanks @lion7! FWIW, #184 is pretty slick but it seems like #185 would be the preferred approach for consistency with the specification terminology across the codebase.
@lion7 #184 works with the spring (spring-boot) generator, #185 only generates File
istead of MultipartFile
as parameter
I also used a work around. With the swagger-codegen-maven-plugin
<typeMappings> <typeMapping>multipartFile=org.springframework.web.multipart.MultipartFile</typeMapping> </typeMappings>
@mistriel could you elaborate how you made it work, including your yaml schema example? Because this typemapping does nothing on our side.
@shathor this is the relevant part from my YAML :
/media/upload:
post:
tags:
- media
summary: Upload media file to storage
operationId: uploadFile
produces:
- application/json
requestBody:
content:
multipart/form-data:
schema:
type: object
properties:
required: true
file:
type: multipartFile
required: true
classification:
required: true
$ref: '#/components/schemas/MediaClassification'
visibility:
required: true
$ref: '#/components/schemas/Visibility'
Note that i also downloaded the entire templates and used them as part of the maven build :
<properties>
<checkstyle.skip>true</checkstyle.skip><!-- set to true since code is generated -->
<findbugs.skip>true</findbugs.skip><!-- set to true since code is generated -->
<swagger.resources>${project.basedir}/src/main/resources/swagger/</swagger.resources>
</properties>
<plugin>
<groupId>io.swagger.codegen.v3</groupId>
<artifactId>swagger-codegen-maven-plugin</artifactId>
<executions>
<execution>
<id>generate swagger</id>
<phase>generate-sources</phase>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<inputSpec>${swagger.resources}/app-server-api.yaml</inputSpec>
<language>spring</language>
<templateDirectory>${swagger.resources}/templates/</templateDirectory>
<generateApiTests>false</generateApiTests>
<generateModelTests>false</generateModelTests>
<generateSupportingFiles>false</generateSupportingFiles>
<typeMappings>
<typeMapping>multipartFile=org.springframework.web.multipart.MultipartFile</typeMapping>
</typeMappings>
<configOptions>
<sourceFolder>src/main/java</sourceFolder>
<modelPackage>xxx.xxx.xxx.payload</modelPackage>
<apiPackage>xxx.xxx.xxx.api</apiPackage>
<dateLibrary>java8</dateLibrary>
<java8>true</java8>
<interfaceOnly>true</interfaceOnly>
<library>spring-mvc</library>
<delegatePattern>false</delegatePattern>
<useTags>true</useTags>
<hideGenerationTimestamp>true</hideGenerationTimestamp>
</configOptions>
</configuration>
</execution>
</executions>
</plugin>
And mainly customized the api.mustache file make sure it imports :
import org.springframework.web.multipart.MultipartFile;
I see, thanks a lot. I was hoping to get by without modifying the templates.
I see, thanks a lot. I was hoping to get by without modifying the templates.
Sorry, the rest of it is protected by our IP, yet this should do the work for you.
I got another workaround. In the maven build add:
<typeMappings>
<typeMapping>File=org.springframework.core.io.InputStreamSource</typeMapping>
</typeMappings>
The YAML part:
requestBody:
content:
multipart/form-data:
schema:
type: object
properties:
file:
type: string
format: binary
myOtherProperty:
$ref: '#/components/schemas/MyType'
type: string
required:
- file
- myOtherProperty
PR https://github.com/swagger-api/swagger-codegen-generators/pull/184 got merged a few days ago so this should be fixed in the next release
@jglynn PR #185 is now also merged. I would suggest closing this issue :)
Using version 3.0.19 I still have to use the workarround
<typeMappings>
<typeMapping>multipartFile=org.springframework.web.multipart.MultipartFile</typeMapping>
</typeMappings>
to have a MutlipartFile when I want an array of file in the requestBody.
documents:
type: array
items:
type: multipartFile
format: binary
Seems the problem is still present.
- The problem is still here
- The problem is still here
The problem is still here