VRaptor

Exemplo de 1 minuto: download

O exemplo a seguir mostra como disponibilizar o download para seu cliente. Note novamente a simplicidade na implementação:

@Controller
public class PerfilController {
    
    public File foto(Perfil perfil) {
        return new File("/path/para/a/foto." + perfil.getId()+ ".jpg");
    }
}

Adicionando mais informações no download

Se você quiser adicionar mais informações ao download você pode retornar um FileDownload:

@Controller
public class PerfilController {
    public Download foto(Perfil perfil) {
        File file = new File("/caminho/para/a/foto." + perfil.getId()+ ".jpg");
        String contentType = "image/jpg";
        String filename = perfil.getNome() + ".jpg";

        return new FileDownload(file, contentType, filename);
    }
}

Para as situações em que você tem um InputStream, você pode utilizar o InputStreamDownload, conforme o exemplo abaixo:

public Download foto(Perfil perfil) {
    InputStream stream = [...];
    String contentType = "image/jpg";

    return new InputStreamDownload(stream, contentType, filename);
}

E como outra opção há o ByteArrayDownload, usado quando você tem um array de bytes.

public Download foto(Perfil perfil) {
    byte[] conteudoFoto = [...];
    String contentType = "image/jpg";

    return new ByteArrayDownload(conteudoFoto, contentType, filename);
}

Você também pode enviar uma lista de arquivos para download, e desta forma eles serão enviados ao browser comprimidos em um arquivo Zip.

public Download fotos() {
    Path foto01 = new File("/caminho/para/a/foto01.jpg").toPath();
    Path foto02 = new File("/caminho/para/a/foto02.jpg").toPath();
    return new ZipDownload("fotos.zip", foto01, foto02);
}

Usando o DownloadBuilder

DownloadBuilder é uma classe útil para ajudar você a criar instâncias da classe Download, usando uma interface fluente. Para criar uma instância de um FileDownload você pode escrever o seguinte código:

FileDownload download = DownloadBuilder.of(meuArquivo)
    .withFileName("curriculo.txt") // opcional, o padrão é File.getName()
    .withContentType("text/plain") // optional, não será enviado se nulo
    .downloadable() // opcional, o padrão é inline content
    .build();

Upload

Para ativar o suporte a upload é necessário adicionar as bibliotecas commons-upload e commons-io em seu classpath. Veja mais informações aqui.

**Nota: ** O upload funciona apenas com métodos do seu controller anotados com @Post. @Get, @Put e demais verbos não são suportados.

Exemplo de 1 minuto: upload

Para receber um upload você precisa receber um UploadedFile em seu método conforme o exemplo abaixo. O UploadedFile retorna o arquivo como um InputStream. Com isso você pode copiar o arquivo para o disco facilmente.

public void atualizaFoto(Perfil perfil, UploadedFile foto) {
    File fotoSalva = new File("/path/to/file/repository", foto.getFileName());
    foto.writeTo(fotoSalva);
    dao.atribui(fotoSalva, perfil);
}

Sobrescrevendo as configurações de upload

Há duas formas para alterar as configurações de upload.

A primeira forma é estendendo a classe DefaultMultipartConfig. Isto é útil quando você precisa alterar o diretório temporário de arquivos ou o tamanho máximo do upload de forma global.

O valor padrão para o upload é de 2MB para cada arquivo, e o mesmo valor para a soma de todos os arquivos. Mas estes valores podem ser facilmente alterados como você pode ver no exemplo abaixo:

@Specializes
@ApplicationScoped
public class CustomMultipartConfig extends DefaultMultipartConfig {

    // alteramos o tamanho total do upload para 50MB
    public long getSizeLimit() {
        return 50 * 1024 * 1024;
    }

    // alteramos o tamanho do upload de cada arquivo para 20MB
    public long getFileSizeLimit() {
        return 20 * 1024 * 1024;
    }
}

A segunda forma é usando a anotação UploadSizeLimit, que permite alterar a configuração do upload para um único método. No exemplo abaixo alteramos a configuração para permitir que cada arquivo tenha no máximo 10MB e o upload total tenha no máximo 40MB:

@UploadSizeLimit(sizeLimit=40 * 1024 * 1024, fileSizeLimit=10 * 1024 * 1024)
public void atualizaFoto(Perfil perfil, UploadedFile foto) {
    [...]
}

A configuração pela anotação tem maior prioridade em relação a configuração global. Você pode usar as duas, porém se um método possuir a anotação UploadSizeLimit, estes valores serão usados para validar o tamanho do upload, ignorando a configuração global.

Alterando o formulário de envio

Para que o browser possa fazer o upload corretamente, você precisa adicionar o atributo enctype para multipart/form-data:

<form action="minha-action" method="post" enctype="multipart/form-data">

Validando o upload

Quando o tamanho máximo para upload de arquivo exceder o valor configurado, o VRaptor adiciona uma mensagem no objeto Validator.