Ako rýchlo rozbehať multipart upload súborov cez HTTP? Ak máte k dispozícii servlety 3.x, môžete ich nakonfigurovať veľmi jednoducho.
Budeme potrebovať:
- Spring 4.0 a novší
- zapnúť v springáckom web initializéri podporu pre multiparty
- deklarovať v springáckom webovom kontexte podporu pre multiparty, ktorá sa využije v kontroléroch
Zapnutie podpory pre multiparty
Vo web inicializéri (analógia web.xml
) zapneme podporu pre multiparty s použitím štandardov servletov 3.x:
import javax.servlet.MultipartConfigElement;
import javax.servlet.ServletRegistration.Dynamic;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
public class WebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
/* ... */
private static final String DEFAULT_UPLOAD_LOCATION = null;
@Override
protected void customizeRegistration(Dynamic registration) {
registration.setMultipartConfig(new MultipartConfigElement(DEFAULT_UPLOAD_LOCATION));
}
}
Týmto spôsobom dosiahneme ukladanie uploadnutých súborov do RAMky. Ak chceme súbory ukladať do dočasného adresára, môžeme ho nastaviť v konštruktore triedy MultipartConfigElement
.
Zapnutie podpory v aplikačnom kontexte
Do springáckeho aplikačného kontextu stačí dodať bean typu MultipartResolver
:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.multipart.MultipartResolver;
import org.springframework.web.multipart.support.StandardServletMultipartResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
@Configuration
@EnableWebMvc
@ComponentScan(basePackages="sk.upjs.ics.novotnyr.smmd")
public class WebApplicationContext {
@Bean
public MultipartResolver multipartResolver() {
return new StandardServletMultipartResolver();
}
}
V tomto prípade sme zaregistrovali bean pre podporu multipartov založenú na servletoch 3.X.
Ukážkový kontrolér
K uploadnutému súboru môžeme pristúpiť pomocou parametra v handlerovej metóde kontroléra. Parameter vyzerá takto:
@RequestParam MultipartFile file
- musí byť typu
MultipartFile
- musí byť anotovaný ako
@RequestParam
- jeho názov sa musí zhodovať s názvom ovládacieho prvku vo formulári.
Upload sa tak namapuje na HTML element:
<input type="file" name="file" />
Všimnite si, že hodnota atribútu name
sa musí zhodovať s názvom parametra metódy (file
).
Metóda kontroléra môže vyzerať nasledovne:
@RequestMapping(method = POST)
public void upload(@RequestParam MultipartFile file) {
log.info("File "
+ file.getOriginalFilename()
+ " was uploaded (" + file.getSize() + " bytes)");
}
Objekt MultipartFile
predstavuje uploadnutý súbor, z ktorého môžeme vyťahovať bajty, inputstreamy, a podobne.
Spustenie s curl
om
Spustiť to môžeme cez curl
:
curl -v --form file=@pretty-pig.png -X POST http://localhost:8080/files
Požiadavka
> POST /files HTTP/1.1
> User-Agent: curl/7.31.0
> Host: localhost:8080
> Accept: */*
> Content-Length: 1146
> Expect: 100-continue
> Content-Type: multipart/form-data; boundary=----------------------------2d8a474ac558
Odpoveď
< HTTP/1.1 100 Continue
< HTTP/1.1 200 OK
< Date: Mon, 09 Feb 2015 06:46:31 GMT
< Content-Length: 0
Demo
Zdrojový kód sa nachádza na GitHube.
Záludnosti
HTTP PUT nefunguje
Multipart upload funguje len pre HTTP POST! (HTTP PUT fungovať nebude).
Servlety 2.5 a staršie
Ak nemáte k dispozícii servlety 3.x, môžete využiť knižnicu commons-upload
. V tomto prípade sa vo web inicializéri nič nebude konfigurovať (napokon, podpora pre web inicializéry v tejto staršej špecifikácii ani nie je), a v aplikačnom kontexte nadeklarujete @Bean
typu org.springframework.web.multipart.commons.CommonsMultipartResolver
.
Podpora pre štandardné Part
y
Namiesto parametra typu MultipartFile
môžete pri servletoch 3.x použiť aj parameter typu javax.servlet.http.Part
Anotácia @RequestPart
Namiesto anotácie @RequestParam
môžete použiť aj anotáciu @RequestPart
. V tomto prípade sa každý objekt v multipart požiadavke preženie cez HttpMessageConverter
y, kde sa bude brať do úvahy Content-Type
jednotlivých častí. Takto možno v multipart požiadavke poslať naraz napr. súbor, JSON a ďalšie parametre. Ak bude part s JSONom mať správny ContentType
, parameter handlujúcej metódy sa automaticky môže previesť cez message converter na správny javácky objekt.