Spring a podpora pre Multipart HTTP Upload

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 curlom

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é Party

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 HttpMessageConvertery, 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.

Zdroje

Pridaj komentár

Vaša e-mailová adresa nebude zverejnená. Vyžadované polia sú označené *