Método:
public void upload(List<UploadedFile> arquivos) {
}
Formulário:
<input name="arquivos[]" type="file" multiple="multiple" />
Resultado:
Meu List tem sempre size 1 e o único arquivo é sempre o último da lista selecionada.
Alguma solução?
Método:
public void upload(List<UploadedFile> arquivos) {
}
Formulário:
<input name="arquivos[]" type="file" multiple="multiple" />
Resultado:
Meu List tem sempre size 1 e o único arquivo é sempre o último da lista selecionada.
Alguma solução?
lauronolasco, acho que isso é uma feature do HTML 5, e não sei se é suportado em todos os browsers (bem possível que não)
na verdade nem sabia que isso era possível 
o que o pessoal costuma usar é um plugin como o JQuery uploadify
Pelos meus testes já funciona no firefox e o chrome…
Vi também este post http://www.guj.com.br/java/137522-vraptor-3–upload-select-multiple que trata de select multiple… achei que poderia ter uma solução parecida.
Vou me aprofundar mais nesse uploadfy…
tá com a última versão do VRaptor?
Estava com a 3.3.1…
Acabei de baixar a 3.4 para testar…
Após teste com a v3.4, continua sem suporte ao upload multiplo. Vou testar o uploadfy agora…
Abre uma issue no VRaptor pra suportar isso, por favor?
Tenho uma aplicação que usa o plugin do jQuery jquery-file-upload, aqui tem uma demo do plugin http://aquantum-demo.appspot.com/file-upload.
Gostei muito, e tem suporte a múltiplos uploads.
Olá Pessoal,
Eu fiz um quebra galho para resolver este problema enquanto a galera do vraptor trabalha nessa atualização:
@Intercepts(before=ResourceLookupInterceptor.class, after = {})
@RequestScoped
public class MultipleUploadInterceptor extends CommonsUploadMultipartInterceptor {
private static final Logger logger = LoggerFactory.getLogger(MultipleUploadInterceptor.class);
private final HttpServletRequest request;
private final MutableRequest parameters;
private final ServletFileUploadCreator fileUploadCreator;
private final MultipartConfig config;
public MultipleUploadInterceptor(HttpServletRequest request,
MutableRequest parameters, MultipartConfig cfg,
Validator validator, ServletFileUploadCreator fileUploadCreator) {
super(request, parameters, cfg, validator, fileUploadCreator);
this.request = request;
this.parameters = parameters;
this.config = cfg;
this.fileUploadCreator = fileUploadCreator;
}
@SuppressWarnings("unchecked")
public void intercept(InterceptorStack stack, ResourceMethod method, Object instance) throws InterceptionException {
FileItemFactory factory = createFactoryForDiskBasedFileItems(config.getDirectory());
ServletFileUpload uploader = fileUploadCreator.create(factory);
uploader.setSizeMax(config.getSizeLimit());
try {
final List<FileItem> items = uploader.parseRequest(request);
logger.debug("Found {} attributes in the multipart form submission. Parsing them.", items.size());
final Multimap<String, String> params = LinkedListMultimap.create();
int i = 0;
for (FileItem item : items) {
String name = item.getFieldName();
name = name.replace("[]", "[" + i + "]");
if (item.isFormField()) {
logger.debug("{} is a field", name);
params.put(name, getValue(item));
} else if (isNotEmpty(item)) {
logger.debug("{} is a file", name);
processFile(item, name);
} else {
logger.debug("A file field was empty: {}", item.getFieldName());
}
i++;
}
for (String paramName : params.keySet()) {
Collection<String> paramValues = params.get(paramName);
parameters.setParameter(paramName, paramValues.toArray(new String[paramValues.size()]));
}
} catch (final SizeLimitExceededException e) {
reportSizeLimitExceeded(e);
} catch (FileUploadException e) {
logger.warn("There was some problem parsing this multipart request, "
+ "or someone is not sending a RFC1867 compatible multipart request.", e);
}
stack.next(method, instance);
}
private String getValue(FileItem item) {
String encoding = request.getCharacterEncoding();
if (!Strings.isNullOrEmpty(encoding)) {
try {
return item.getString(encoding);
} catch (UnsupportedEncodingException e) {
logger.warn("Request have an invalid encoding. Ignoring it");
}
}
return item.getString();
}
private boolean isNotEmpty(FileItem item) {
return item.getName().length() > 0;
}
}
David, quer mandar essa correção pro VRaptor?
e mande um pull request
Olá Lucas,
Eu alterei o arquivo.
Lembrando que para funcionar é necessário colocar os parêntesis no name:
<input type="file" name="files[]" multiple="multiple" />
E no controller deve receber um List ou array:
public void upload(List<UploadedFile> files)
public void upload(UploadedFile[] files)
Abraços,
David
obrigado, já fiz o merge =)
Lucas, fiz uma nova atualização, havia um problema no contador caso fosse enviado mais de um parâmetro no submit.
Tentei fazer uns testes aqui, mas por alguma razão meu FF 7 abriu um campo file normal. Quais os browsers já possuem suporte a essa feature?
Baseado no teu código fiz um fix para o upload do servlet3 (componente que é baseado no que você usou para commons-fileupload).
Incluí o atributo de classe:
Incluí o seguinte método privado para fixar o nome.
private String fixIndexedParameters(String name) {
if (name.contains("[]")) {
String newName = name.replace("[]", "[" + (indexes.count(name)) + "]");
indexes.add(name);
logger.debug("{} was renamed to {}", name, newName);
name = newName;
}
return name;
}
Depois é só adicionar a chamada para este método lá onde você pega o nome do parametro. No caso do componente para servlet 3 ficou assim:
String name = part.getName();
name = fixIndexedParameters(name);
Fiz uns testes com esse HTML e controller abaixo e tudo funcionou bem. Veja se isso te ajuda.
[code]
<input type="submit" /> <br />
</form>[/code]
[code] @Post("/upload")
public void upload(UploadedFile[] files, String[] comments, String text) {
for (UploadedFile file : files) {
System.out.println(file);
}
for (String comment : comments) {
System.out.println(comment);
}
System.out.println(text);
}[/code]
O código é bem trivial e fácil de entender. A única coisa mais complexa é o Multiset, do Guava Libraries, que é um “Bag Set” que permite adicionar vários elementos e depois contar quantos elementos iguais eu tenho. Assim facilita o contador, que pelo que notei pelos pull-requests no Github, era o problema que você tinha.
Abraços
Com o GAE ocorre também o mesmo problema, único arquivo enviado é sempre o último da lista selecionada.
A classe sugerida como correção pelo David em : https://github.com/caelum/vraptor/blob/master/vraptor-core/src/main/java/br/com/caelum/vraptor/interceptor/multipart/CommonsUploadMultipartInterceptor.java
não resolve o problema para o GAE devido ao uso da escrita em arquivo.
Alguma solução ou deve-se abrir uma issue?
Este problema já foi resolvido.
Amigos, revivendo esse codigo,
Estou passando pelo mesmo cenario, mas nao estou conseguindo fazer esse troço funcionar. Por gentileza, vejam:
JSP:
<input type="file" name="files[]" multiple />
Controller:
@Post
public void upload(List<UploadedFile> files){
}
Exception:
Caused by: br.com.caelum.iogi.exceptions.InvalidTypeException: Cannot instantiate abstract type interface br.com.caelum.vraptor.interceptor.multipart.UploadedFile
at br.com.caelum.iogi.ObjectInstantiator.expectingAConcreteTarget(ObjectInstantiator.java:40)
at br.com.caelum.iogi.ObjectInstantiator.instantiate(ObjectInstantiator.java:26)
at br.com.caelum.iogi.MultiInstantiator.instantiate(MultiInstantiator.java:20)
at br.com.caelum.vraptor.http.iogi.VRaptorInstantiator.instantiate(VRaptorInstantiator.java:85)
at br.com.caelum.iogi.collections.IndexedListInstantiator.instantiate(IndexedListInstantiator.java:34)
at br.com.caelum.iogi.collections.ListInstantiator.instantiate(ListInstantiator.java:25)
at br.com.caelum.iogi.collections.ListInstantiator.instantiate(ListInstantiator.java:10)
at br.com.caelum.vraptor.http.iogi.NullDecorator.instantiate(NullDecorator.java:25)
at br.com.caelum.iogi.MultiInstantiator.instantiate(MultiInstantiator.java:20)
at br.com.caelum.vraptor.http.iogi.VRaptorInstantiator.instantiate(VRaptorInstantiator.java:85)
... 59 more
Na hora de injetar o valor dos parametros o vraptor não está conseguindo encontrar o valor do parametro “files”, visto que o mesmo está na request com a chave “files[numero]”. Dessa forma ocorre a tentativa de instanciar o UploadedFile e o erro…
Conseguem enxergar algo que está errado? Me parece que está igual aos outros exemplos desse topico.
Obrigado amigos!