Vraptor - Upload

Blza pessoal,
Continuando os testes que estou fazendo no VRaptor, cheguei na parte de Upload.
Estou testando o seguinte código, mas o UploadedFile está vindo sempre nulo.

Controller:

import javax.servlet.http.HttpServletRequest;

import br.com.caelum.vraptor.Path;
import br.com.caelum.vraptor.Resource;
import br.com.caelum.vraptor.interceptor.multipart.UploadedFile;

@Resource
public class IndexController {
	
        private HttpServletRequest request;
	
	public IndexController(HttpServletRequest request) {
		this.request = request;
	}

	@Path("/")
	public void index() {
		
	}
	
	public void upload(UploadedFile arquivo) {
		if(arquivo == null) {
			System.out.println("Erro upload");
		}
	}

}

JSP:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<html>
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
	<title></title>
</head>
<body>
	<form action="<c:url value="/index/upload"/>" method="post">
		<input type="file" name="arquivo" /> <br />
		<input type="submit" value="Salvar" />
	</form>
</body>
</html>

O que estou fazendo errado?

[]´s

Daniel

Sempre que você envia arquivos, o formato do request é diferente. Para isso você precisa enviar o form diferente também indicando o parametro enctype=“multpart/form-data”.

Valeu Garcia, mas mesmo utilizando a declaração do form que você passou o sistema continua não enviando o arquivo.

[]´s

faltou um “i”:
enctype=“multipart/form-data”

[quote=lucascs]faltou um “i”:
enctype=“multipart/form-data”[/quote]

:oops: oops

Fiz o ajuste na declaração e continua vindo null.

Agora disparou um HTTP500…
Em qual JAR tem classe DeferredFileOutputStream?

Segue o erro:

HTTP Status 500 -

type Exception report

message

description The server encountered an internal error () that prevented it from fulfilling this request.

exception

javax.servlet.ServletException: Filter execution threw an exception

root cause

java.lang.NoClassDefFoundError: org/apache/commons/io/output/DeferredFileOutputStream
	org.apache.commons.fileupload.disk.DiskFileItemFactory.createItem(DiskFileItemFactory.java:196)
	org.apache.commons.fileupload.FileUploadBase.parseRequest(FileUploadBase.java:358)
	org.apache.commons.fileupload.servlet.ServletFileUpload.parseRequest(ServletFileUpload.java:126)
	br.com.caelum.vraptor.interceptor.multipart.MultipartInterceptor.intercept(MultipartInterceptor.java:84)
	br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:46)
	br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	br.com.caelum.vraptor.interceptor.InterceptorListPriorToExecutionExtractor.intercept(InterceptorListPriorToExecutionExtractor.java:46)
	br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:46)
	br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	br.com.caelum.vraptor.interceptor.FlashInterceptor.intercept(FlashInterceptor.java:80)
	br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:46)
	br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	br.com.caelum.vraptor.interceptor.ResourceLookupInterceptor.intercept(ResourceLookupInterceptor.java:67)
	br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:46)
	br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	br.com.caelum.vraptor.core.DefaultRequestExecution.execute(DefaultRequestExecution.java:62)
	br.com.caelum.vraptor.VRaptor$1.insideRequest(VRaptor.java:91)
	br.com.caelum.vraptor.ioc.spring.SpringProvider.provideForRequest(SpringProvider.java:55)
	br.com.caelum.vraptor.VRaptor.doFilter(VRaptor.java:88)

root cause

java.lang.ClassNotFoundException: org.apache.commons.io.output.DeferredFileOutputStream
	org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1387)
	org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1233)
	java.lang.ClassLoader.loadClassInternal(Unknown Source)
	org.apache.commons.fileupload.disk.DiskFileItemFactory.createItem(DiskFileItemFactory.java:196)
	org.apache.commons.fileupload.FileUploadBase.parseRequest(FileUploadBase.java:358)
	org.apache.commons.fileupload.servlet.ServletFileUpload.parseRequest(ServletFileUpload.java:126)
	br.com.caelum.vraptor.interceptor.multipart.MultipartInterceptor.intercept(MultipartInterceptor.java:84)
	br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:46)
	br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	br.com.caelum.vraptor.interceptor.InterceptorListPriorToExecutionExtractor.intercept(InterceptorListPriorToExecutionExtractor.java:46)
	br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:46)
	br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	br.com.caelum.vraptor.interceptor.FlashInterceptor.intercept(FlashInterceptor.java:80)
	br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:46)
	br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	br.com.caelum.vraptor.interceptor.ResourceLookupInterceptor.intercept(ResourceLookupInterceptor.java:67)
	br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:46)
	br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:59)
	br.com.caelum.vraptor.core.DefaultRequestExecution.execute(DefaultRequestExecution.java:62)
	br.com.caelum.vraptor.VRaptor$1.insideRequest(VRaptor.java:91)
	br.com.caelum.vraptor.ioc.spring.SpringProvider.provideForRequest(SpringProvider.java:55)
	br.com.caelum.vraptor.VRaptor.doFilter(VRaptor.java:88)

testei aqui com esse form e funcionou:

<body>
	<form action="<c:url value="/index/upload"/>" enctype="multipart/form-data" method="post">
		<input type="file" name="arquivo" /> <br />
		<input type="submit" value="Salvar" />
	</form>
</body>
</html>

será que seu browser não está fazendo cache da página? ve no codigo fonte se o form tá direitinho…

[]'s

Commons IO

org/apache/commons/io/output/DeferredFileOutputStream

tá no commons-io-1.3.2.jar
esse jar está em lib/optional no zip do vraptor ou vc pode baixar no site oficial http://commons.apache.org/io/

Opa, agora funcionou.
O estranho é que o erro só disparou depois que eu adicionei mais um Objeto para ser passado no form.
Agora está assim:

	<form action="<c:url value="/index/upload"/>" enctype="multipart/form-data" method="post">
		<input type="file" name="arquivo" /> <br />
		<input type="text" name="contato.nome" />
		<input type="submit" value="Salvar" />
	</form>
	public void upload(Contato contato, UploadedFile arquivo) {
		if(arquivo == null) {
			System.out.println("Erro upload");
		}
		if(contato != null) {
			System.out.println(contato.getNome());
		}
	}

Pessoal, valeu pela ajuda.

[]´s

Daniel

[quote=lucascs]tá no commons-io-1.3.2.jar
esse jar está em lib/optional no zip do vraptor ou vc pode baixar no site oficial http://commons.apache.org/io/[/quote]

Lucas, eu não sou muito fã desses projetos jakarta-commons-*, uso porque realmente é melhor do que fazer na mão. E pesquisando aqui e alí achei um projeto do google que nem beta é, o Guava, mas nos testes que eu fiz com I/O está super bom. Dê uma olhada, quem sabe em um futuro próximo possa ser útil. Lá diz que possívelmente irá juntar-se ao google collections.

Analisando os pacotes me pareceu um merge com commons-io, commons-lang. Se juntarem os projetos, espero que pelo menos não chamem mais de google-collections.

Legal, vou dar uma olhada =)

parece legal o projeto…

mas a dependência do commons-io não eh do VRaptor, é do commons-fileupload… então infelizmente não dá pra trocar =(

Legal mesmo, gostei muito do que já está implementado e também do roadmap para quando o projeto decolar. Mas te passei o link apenas para você conhecer, pois nem é bom usar essas coisas em versão que-nem-chegaram-a-beta, hehe.

Corrigindo, lí correndo e ainda lí errado. Lá diz que por enquanto há pedaços dele no g-gollections e vice-versa, mas que logo irão regularizar isso.

Abraços

Olá pessoal!

Continuo com uma dúvida em relação a esse assunto. Esse método vai receber um UploadedFile, um arquivo que eu posso manipular, isso? E se eu quiser salvá-lo como se fosse a foto do cadastro de um perfil? Tipo gostaria se salvar no banco essa imagem e já recarregá-la na tela vinda do banco.

Agradeço pela atenção,

Gustavo

O arquivo vai vir como um InputStream…

o VRaptor já possui como dependência o commons-io, que tem um utilitário pra fazer esse tipo de cópia:

UploadedFile upload = //vai vir da requisição
File destino = new File("/onde/eu/vou/salvar");
IOUtils.copyLarge(upload.getFile(), new PrintWriter(destino));

Beleza, isso eu entendi.

Mas e se eu quiser salvar essa imagem em um local que eu possa mostrar depois no browser…
Eu estou usando Vraptor 3 e eu não sei como dizer o caminho onde salvar, para que depois eu consiga mostrar em um tag .

Valeu pela força,

Guto

vc pode receber um RequestInfo no construtor da sua classe e fazer no seu controlador do Upload:

ImagensController(RequestInfo info) {
   String realPath = info.getServletContext().getRealPath("/web/imagens");
   this.imagensDir = new File(realPath);
}

e na lógica do upload:

UploadedFile upload = // vem da requisição:
File destino = new File(imagensDir, "algumNomeUnico.jpg");
IOUtils.copyLarge(upload.getFile(), new PrintWriter(destino));

e é só usar nas jsps essa imagens como vc falou…

[]'s

Boa Noite,

Tentei seguir a lógica do codigo abaixo, a fim de gerar um método para realizar o upload de arquivos.

No entanto, a função IOUtils.copyLarge parece não ser compátivel com o objeto PrintWriter

Estou utilizando o vraptor3
Segue abaixo o código do metodo.

@Path("/upload/file/")
	public void uploadFile(UploadedFile arquivo) {
			if(arquivo == null) {
				System.out.println("Erro upload");
			}
			else
			{
				File destino = new File("c:\\repositorio\\teste1.txt");
				try {
//The method copyLarge(InputStream, OutputStream) in the type IOUtils is not applicable 
// for the arguments (InputStream, PrintWriter)

					IOUtils.copyLarge(arquivo.getFile(), new PrintWriter(destino));
				} catch (IOException e) {
					e.printStackTrace();
					System.out.println("Upload NOK");
				}
			}
	}

Quando uso o método IOUtils.copy, em vez de IOUtils.copyLarge, o arquivo é copiado com zero bytes.

Alguma sugestão?

Obrigado.