Receber arquivo do Web service

Senhores,

Alguém já trabalhou recebendo arquivo binário do webservice? como anexo ele no Web Service e recebo no client?

É complicado isso.

Aqui, já tive algo parecido, o que fiz foi serializar a imagem e enviar normalmente.
Já vi casos onde a imagem era enviada para um FTP, e na mensagem enviada ao o Web Service tinha somente o caminho do arquivo no FTP. Mas não acho essa solução muito inteligente e performática.

A serialização é uma boa alternativa, porém, não sei como iria reagir no caso de grandes arquivos.
Você tem que levar em consideração a integridade do arquivo.

enviar eu consigo(anexando no client), só não consegui ainda receber de volta o arquivo modificado.

estou usando Axis 1.4, jboss e ejb.

Consegui em partes, usando XStream

É possível enviar e receber arquivos dos webservices?
Estou indo mexer com isso, mas nunca trabalhei com Java Web, nem Webservices, só consumindo os serviços da receita (NFe)…
Teriam alguma dica para me passar?
Grato!

cara eh possivel sim, basta voce transformar esse arquivo em array de byte, e colocar em Base64(dessa forma vc preserva os bytes), do outro lado voce decodifica. Voce ira trafegar uma string gigante.

Nossa nunca vi isso… como a receita recebe os XMLs sem precisar fazer isso?
A sim, você está falando de um arquivo do tipo foto, audio e etc etc etc… certo?
Eu tenho que ver se será possível, pois utilizarei ou Android ou TotalCross para acesso o WS, são para ambiente mobile, com limitações de recursos…

Falae Pessoal.

Bom, primeiro post, espero que ajude em alguma coisa. :smiley:

É possível sim enviar arquivos binários via SOAP sem ter que transformá-lo em array de byte e codificá-lo em base 64. Considero esta abordagem (byte[]+b64) uma prática ruim, pois isso vai consumir processamento e banda a toa, sem contar que vai poluir o body da mensagem e se o arquivo for muito grande, vale lembrar que o protocolo SOAP tem um limite para transporte de informações para o body.

Dêem uma olhada na estrutura do envelope SOAP:

Reparem que além do SOAP Part, que é onde vai nosso cabeçalho (HEADER) e o corpo da mensagem (BODY) existe o Attachment Part, que é um espaço exclusivo para o tráfego de arquivos binários.

Os códigos que vou apresentar abaixo não foram compilados, por isso podem apresentar algum pequeno erro, mas nada muito grave. Eles devem compilar com java 1.6

Client Side
Vale lembrar que não achei nenhum gerador de Clients capaz de trabalhar com Attachments, no entanto, é muito fácil montar o envelope SOAP manualmente e enviar os arquivos.

[code]import java.io.ByteArrayOutputStream;
import java.io.File;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.xml.soap.AttachmentPart;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPConnection;
import javax.xml.soap.SOAPConnectionFactory;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPMessage;
import javax.xml.soap.SOAPPart;

public class ClientArquivador {

public static void main(String[] args) {
	try {
		
		File file1 = new File("C:\\arquivo.doc");
		DataSource ds1 = new FileDataSource(file1);
		DataHandler dh1 = new DataHandler(ds1);
		
		File file2 = new File("C:\\arquivo1.zip");
		DataSource ds2 = new FileDataSource(file2);
		DataHandler dh2 = new DataHandler(ds2);
		
		SOAPConnectionFactory soapConnectionFactory = SOAPConnectionFactory.newInstance();
		SOAPConnection connection = soapConnectionFactory.createConnection();

		MessageFactory factory = MessageFactory.newInstance();
		SOAPMessage message = factory.createMessage();

		SOAPPart soapPart = message.getSOAPPart();
		SOAPEnvelope envelope = soapPart.getEnvelope();
		SOAPBody body = message.getSOAPBody();
		
		envelope.addAttribute(envelope.createName("xmlns:enviarDocumentos"), "http://service.odoni.com.br/");
		SOAPElement bodyElement = body.addChildElement(envelope.createName("enviarDocumentos", "enviarDocumentos", ""));
		bodyElement.addChildElement("arg0").addTextNode("Param qualquer");
		
		AttachmentPart attachment1 = message.createAttachmentPart(dh1);
		AttachmentPart attachment2 = message.createAttachmentPart(dh2);
		
		message.addAttachmentPart(attachment1); 
		message.addAttachmentPart(attachment2);
		message.saveChanges();
		
		// Imprimindo o REQUEST
		ByteArrayOutputStream baosRequest = new ByteArrayOutputStream();
		System.out.println("\nREQUEST:\n");
		message.writeTo(baosRequest);
		System.out.println(new String(baosRequest.toByteArray()));

		URL endpoint = new URL("http://localhost:8080/seuServico");
		
		SOAPMessage response = connection.call(message, endpoint);

		connection.close();
		
		// Imprimindo o RESPONSE
		ByteArrayOutputStream baosResponse = new ByteArrayOutputStream();
		System.out.println("\nRESPONSE:\n");
		response.writeTo(baosResponse);
		System.out.println(new String(baosResponse.toByteArray()));
		
	} catch (Exception ex) {
		ex.printStackTrace();
	}
}

}
[/code]

Server Side
Aqui, vamos manipular o MessageContext, que é a estrutura que representa o protocolo SOAP, através dele conseguimos manipular além da Attachment Part, o SOAP Part.

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.Map;

import javax.activation.DataHandler;
import javax.annotation.Resource;
import javax.jws.WebService;
import javax.xml.ws.WebServiceContext;
import javax.xml.ws.handler.MessageContext;

@WebService
public class Arquivador {
	@Resource
	WebServiceContext wsContext;
	
	public String enviarDocumentos(String marca) {
		MessageContext context = wsContext.getMessageContext();
		Map request = (Map) context.get(MessageContext.INBOUND_MESSAGE_ATTACHMENTS);
		String retorno = "OK";
			
		DataHandler dhAmostras = (DataHandler) request.get("1");
		DataHandler dhEnderecos = (DataHandler) request.get("2");

		ByteArrayOutputStream baosAmostras = null;
		ByteArrayOutputStream baosEnderecos = null;
		
		try {
			baosAmostras = new ByteArrayOutputStream();
			dhAmostras.writeTo(baosAmostras);
			
			baosEnderecos = new ByteArrayOutputStream();
			dhEnderecos.writeTo(baosEnderecos);
		
		
		InputStream amostra = new ByteArrayInputStream(baosAmostras.toByteArray());
		InputStream endereco = new ByteArrayInputStream(baosEnderecos.toByteArray());
		
		//Manipula os arquivos aqui
		
		} catch (Exception e) {
			retorno = "Erro inesperado. " + e.getMessage();
		}
		
		return retorno;
	}

}

No Client, o que faço é montar o envelope SOAP e colocar os arquivos em seu Attachment Part. Mais uma vez, não achei nenhum gerador de client (como o Axis, por exemplo), que faça isso automaticamente, por isso montamos o envelope SOAP na mão.

No Server, apenas manipulo o MessageContext para recuperar as informações contidas no Attachment Part. Reparem que eles vêm em um Map com as chaves de 1 até a quantidade de arquivos anexados.

Eu poderia dar mais detalhes desta implementação, mas teria que provavelmente escrever um livro para isso. Por isso se tiverem dúvidas pontuais, respondam este post que respondo em seguida.

Abraços!

Amigo, fiz o exemplo acima apresentado porém não chega nenhum arquivo , ou seja a linha abaixo sempre chega vazia :

// Map sempre vazio
Map request = (Map) context.get(MessageContext.INBOUND_MESSAGE_ATTACHMENTS);   

se poder da uma ajudinha , obrigado…