[RESOLVIDO] como fazer upload em arquivo .pdf ou .doc

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).

1 curtida

Nunca fiz upload na mão…

Eu utilizo o vraptor na minha aplicação tanto o upload quanto o download dele são faceis de implementar.

http://vraptor.caelum.com.br/pt/docs/download-e-upload/

Não use getString, use isto:

http://commons.apache.org/fileupload/apidocs/org/apache/commons/fileupload/FileItem.html#getInputStream()

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.

Resolvido
Fiz exatamente o que me indicaram
troquei a string do item pelo inputStream

					String realName = extractFilename(item.getName());
					int len = 0;
					InputStream is = item.getInputStream();
					File uploadedFile = new File(REPOSITORIO+"\\"+realName);
					FileOutputStream fos = new FileOutputStream(uploadedFile);
					ByteOutputStream bos = new ByteOutputStream();
					byte[] buf = new byte[1024];
					while((len = is.read(buf, 0, 1024)) != -1)
						bos.write(buf, 0, len);
					buf = bos.toByteArray();
					fos.write(bos.getBytes());
					fos.close();

tem um pequeno problema ainda, o toByteArray ser deprecated. Assim que resolver essa posto aqui

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:

buf = bos.toByteArray();

por

buf = bos.toString().getBytes();

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