Preciso fazer upload de arquivo do cliente para o servidor.
o cliente escolherá um arquivo em sua máquina e este será gravado no servidor.
Depois de muito pesquisar, consegui encontrar a solução abaixo, mas ele só consegue fazer corretamente se eu escolher um arquivo .txt, se escolher um .doc ou um .pdf, o arquivo é gravado mas não abre.
public class DocumentoUploadServletOLD extends HttpServlet {
private static final long serialVersionUID = 1L;
private static final int SIZE_MAX = 50000*1024*1024;
private static final File REPOSITORIO = new File("C:/Java/");
/**
* @see HttpServlet#HttpServlet()
*/
public DocumentoUploadServletOLD() {
super();
}
/**
* @see HttpServlet#service(HttpServletRequest request, HttpServletResponse response)
*/
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
DiskFileItemFactory factory = new DiskFileItemFactory();
factory.setSizeThreshold(SIZE_MAX);
factory.setRepository(REPOSITORIO);
ServletFileUpload upload = new ServletFileUpload(factory);
try {
List items = upload.parseRequest(request);
Iterator iter = items.iterator();
while (iter.hasNext()) {
FileItem item = (FileItem) iter.next();
if (item.isFormField()) {
String name = item.getFieldName();
String value = item.getString();
String nomeArquivo = extractFilename(item.getName());
System.out.println("item.getFieldName(): "+item.getFieldName());
System.out.println("item.getName(): "+item.getName());
System.out.println("item.getString(): "+item.getString());
} else {
String realName = extractFilename(item.getName());
String value = item.getString();
File uploadedFile = new File(REPOSITORIO+"\\"+realName);
FileOutputStream fos = new FileOutputStream(uploadedFile);
fos.write(value.getBytes());
fos.close();
}
}
} catch (FileUploadException e) {
e.printStackTrace();
}
RequestDispatcher dispatcher = request.getRequestDispatcher("/jsp/documentosUploadArquivo.jsp");
dispatcher.forward(request, response);
}
private String extractFilename(String filePathName) {
if (filePathName == null)
return null;
int dotPos = filePathName.lastIndexOf( '.' );
int slashPos = filePathName.lastIndexOf( '\\' );
if ( slashPos == -1 )
slashPos = filePathName.lastIndexOf( '/' );
if ( dotPos > slashPos ) {
return filePathName.substring( slashPos > 0 ? slashPos + 1 : 0);
}
return filePathName.substring( slashPos > 0 ? slashPos + 1 : 0 );
}
String value = item.getString();
File uploadedFile = new File(REPOSITORIO+"\\"+realName);
FileOutputStream fos = new FileOutputStream(uploadedFile);
fos.write(value.getBytes());
O conteúdo dos dados está em uma String (em item.getString())? Que pecado. Isso irá corromper os dados (somente vai dar certo para um arquivo texto mesmo).
Fica por sua conta você entender como é que se usa o InputStream retornado por esse método. Por favor, não use o método read que lê um byte de cada vez, porque ele é muito lento. Use o método read que lê um array de bytes de cada vez. Evite carregar o arquivo inteiramente para a memória - você pode ter arquivos .doc ou .pdf que podem estourar sua memória.
na API IOUtils da commons.apache.org/ realmente mostra o toByteArray como deprecated e diz para trocar por String.getBytes().
me dei ao luxo de simplesmente chamar o toString e dele o getBytes.
Portanto troquei a linha:
Evite gastar memória à toa.
Evite usar ByteArrayOutputStream se você não precisar dele (e evite converter um array de bytes para string, e depois usar String.getBytes - foi isso que causou seu problema de corrupção no arquivo PDF ou DOC).
Faça apenas isto:
String realName = extractFilename(item.getName());
int len = 0;
BufferedInputStream bis = new BufferedInputStream (item.getInputStream());
File uploadedFile = new File(REPOSITORIO+"\\"+realName);
BufferedOutputStream bos = new BufferedOutputStream (new FileOutputStream (uploadedFile));
byte[] buf = new byte[1024];
while((len = bis.read(buf, 0, 1024)) > 0) {
bos.write(buf, 0, len);
}
bos.close();
A propósito, a forma legal de você concatenar um diretório e um nome de arquivo não é assim, nem mesmo usando File.separator. A forma mais legal e que funciona tanto no Windows quanto no Linux ou outro Unix (como o Solaris) é usar um construtor de File que aceita 2 argumentos, sendo um deles um File e outro uma String. Exemplo:
File dir = new File ("nome de um diretorio qualquer");
File path = new File (dir, "nome do arquivo"); // ele põe automaticamente o "\\" ou "/" dependendo do sistema operacional