Spring e Apache FileUpload

Spring e Apache FileUpload

1. Visão geral

A *Apache Commons File Upload Library * nos ajuda a enviar arquivos grandes pelo protocolo HTTP usando o tipo de conteúdo multipart/form-data.

Neste tutorial rápido, veremos como integrá-lo ao Spring.

*2. Dependências do Maven *

Para usar a biblioteca, precisamos do artefato commons-fileupload:

<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.3.3</version>
</dependency>

A versão mais recente pode ser encontrada em Maven Central.

===* 3. Transferindo tudo de uma vez *

Para fins de demonstração, criaremos um Controller processando solicitações com uma carga útil de arquivo:

@PostMapping("/upload")
public String handleUpload(HttpServletRequest request) throws Exception {
    boolean isMultipart = ServletFileUpload.isMultipartContent(request);

    DiskFileItemFactory factory = new DiskFileItemFactory();
    factory.setRepository(
      new File(System.getProperty("java.io.tmpdir")));
    factory.setSizeThreshold(
      DiskFileItemFactory.DEFAULT_SIZE_THRESHOLD);
    factory.setFileCleaningTracker(null);

    ServletFileUpload upload = new ServletFileUpload(factory);

    List items = upload.parseRequest(request);

    Iterator iter = items.iterator();
    while (iter.hasNext()) {
        FileItem item = iter.next();

        if (!item.isFormField()) {
            try (
              InputStream uploadedStream = item.getInputStream();
              OutputStream out = new FileOutputStream("file.mov");) {

                IOUtils.copy(uploadedStream, out);
            }
        }
    }
    return "success!";
}

No começo,* precisamos verificar se a solicitação contém um conteúdo com várias partes *usando o método isMultipartContent encontrado na classe ServletFileUpload da biblioteca.

Por padrão, o* Spring apresenta um * MultipartResolver que precisaremos desativar para usar esta biblioteca. Caso contrário, ele lerá o conteúdo da solicitação antes de chegar ao nosso Controller.

Podemos conseguir isso incluindo essa configuração em nosso arquivo application.properties:

spring.http.multipart.enabled=false

Agora, podemos definir o diretório em que nossos arquivos serão salvos, o limite em que a biblioteca decide gravar no disco e se os arquivos devem ser excluídos após o término da solicitação.

A biblioteca fornece uma classe DiskFileItemFactory que _ assume a responsabilidade da configuração para salvar e limpar arquivos . O método _setRepository define o diretório de destino, com o padrão sendo mostrado no exemplo.

Em seguida, o setSizeThreshold define um tamanho máximo de arquivo.

Em seguida, temos o método setFileCleaningTracker que, quando definido como nulo, deixa os arquivos temporários intocados. Por padrão, ele os exclui após a conclusão da solicitação .

Agora podemos continuar com o tratamento de arquivos real.

Primeiro, criamos nosso ServletFileUpload incluindo nossa fábrica criada anteriormente; em seguida, analisamos a solicitação e geramos uma lista de FileItem, que é a principal abstração da biblioteca para os campos do formulário.

Agora, se sabemos que esse não é um campo de formulário normal, extraímos o InputStream e chamamos o método de cópia útil de IOUtils (para obter mais opções, consulte o link:/convert-input-stream-to- um arquivo [este] tutorial) .

Agora, temos nosso arquivo armazenado na pasta necessária. Geralmente, é uma maneira mais conveniente de lidar com essa situação, pois permite fácil acesso aos arquivos, mas também a eficiência de tempo/memória não é ideal.

Na próxima seção, veremos a API de streaming.

*4. API de streaming *

A API de streaming é fácil de usar, tornando-a uma ótima maneira de processar arquivos grandes simplesmente não copiando para um local temporário:

ServletFileUpload upload = new ServletFileUpload();
FileItemIterator iterStream = upload.getItemIterator(request);
while (iterStream.hasNext()) {
    FileItemStream item = iterStream.next();
    String name = item.getFieldName();
    InputStream stream = item.openStream();
    if (!item.isFormField()) {
       //Process the InputStream
    } else {
        String formFieldValue = Streams.asString(stream);
    }
}

Podemos ver no snippet de código anterior que não incluímos mais um DiskFileItemFactory. Isso ocorre porque,* ao usar a API de streaming, não precisamos dela *.

Em seguida, para processar os campos, a biblioteca fornece um FileItemIterator, que não lê nada até extraí-los da solicitação com o método next.

Finalmente, podemos ver como obter os valores dos outros campos do formulário.

5. Conclusão

Neste artigo, analisamos como podemos usar a Biblioteca de Upload de Arquivos Apache Commons com o Spring para fazer upload e processar arquivos grandes.

Como sempre, o código fonte completo pode ser encontrado over no GitHub.