Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Spring] Support MultiPartFile for file uploads #183

Open
jglynn opened this issue Sep 25, 2018 · 17 comments
Open

[Spring] Support MultiPartFile for file uploads #183

jglynn opened this issue Sep 25, 2018 · 17 comments

Comments

@jglynn
Copy link

jglynn commented Sep 25, 2018

Somewhat similar to #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.

@jglynn
Copy link
Author

jglynn commented Sep 25, 2018

@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.

@lion7
Copy link
Contributor

lion7 commented Sep 26, 2018

@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 #184 and #185

@jglynn
Copy link
Author

jglynn commented Oct 3, 2018

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.

@Andy2003
Copy link

@lion7 #184 works with the spring (spring-boot) generator, #185 only generates File istead of MultipartFile as parameter

@mistriel
Copy link

mistriel commented Mar 3, 2019

I also used a work around. With the swagger-codegen-maven-plugin

<typeMappings> <typeMapping>multipartFile=org.springframework.web.multipart.MultipartFile</typeMapping> </typeMappings>

@shathor
Copy link

shathor commented May 23, 2019

@mistriel could you elaborate how you made it work, including your yaml schema example? Because this typemapping does nothing on our side.

@mistriel
Copy link

@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;

@shathor
Copy link

shathor commented May 26, 2019

I see, thanks a lot. I was hoping to get by without modifying the templates.

@mistriel
Copy link

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.

@shathor
Copy link

shathor commented Jun 12, 2019

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

@lion7
Copy link
Contributor

lion7 commented Jun 12, 2019

PR #184 got merged a few days ago so this should be fixed in the next release

@lion7
Copy link
Contributor

lion7 commented Jan 4, 2020

@jglynn PR #185 is now also merged. I would suggest closing this issue :)

@sebastianblesgen
Copy link

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

@natami
Copy link

natami commented Nov 29, 2021

Seems the problem is still present.

@DenisPekutovskiySetronica
  1. The problem is still here

@david139
Copy link

  1. The problem is still here

@taylorzhangyx
Copy link

The problem is still here

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

10 participants