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.