我有一个Android客户端向soap服务发出请求。 soap服务将图像读入一系列字节并返回一个字节数组(非常大)。这会被视为原始转移类型吗?我问的原因是因为我有服务代码读取图像并打印前5个字节。然后它返回字节数组。
@Override
public byte[] getImage() {
byte[] imageBytes = null;
try {
File imageFile = new File("C:\\images\\car.jpg");
BufferedImage img = ImageIO.read(imageFile);
ByteArrayOutputStream baos = new ByteArrayOutputStream(1000);
ImageIO.write(img, "jpg", baos);
baos.flush();
imageBytes = baos.toByteArray();
baos.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
System.out.println("Got request");
System.out.println("****** FIRST 5 BYTES: ");
for(int i=0; i<5; i++) {
System.out.println("****** " + imageBytes[i]);
}
return imageBytes;
}
服务器上服务的输出是
****** FIRST 5 BYTES:
****** -119
****** 80
****** 78
****** 71
****** 13
当我在我的android模拟器上收到这个时,我打印前5个字节,它们与服务器上打印的完全不同。这是我的android代码:
androidHttpTransport.call(SOAP_ACTION, envelope);
SoapPrimitive resultsRequestSOAP = (SoapPrimitive) envelope.getResponse();
String result = resultsRequestSOAP.toString();
System.out.println("****** RESULT: " + result);
byte[] b = result.getBytes();
System.out.println("****** FIRST 5 BYTES: ");
for(int i=0; i<5; i++) {
System.out.println("****** " + b[i]);
}
输出
****** FIRST 5 BYTES:
****** 105
****** 86
****** 66
****** 79
****** 82
如果我用一个用java编写的简单服务客户端测试它,它工作正常。有什么想法可能会发生这种情况吗?
答案 0 :(得分:11)
@Override
public String getImage() {
byte[] imageBytes = null;
try {
File imageFile = new File("C:\\images\\fiesta.jpg");
BufferedImage img = ImageIO.read(imageFile);
ByteArrayOutputStream baos = new ByteArrayOutputStream(1000);
ImageIO.write(img, "jpg", baos);
baos.flush();
imageBytes = baos.toByteArray();
baos.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
return (imageBytes != null) ? Base64.encodeBase64String(imageBytes) : "";
}
现在,这里是android代码,它将调用服务并获取编码的图像内容,将其解码为字节数组,创建位图并在模拟器中显示它:
public class ImageSoapActivity extends Activity {
private static final String NAMESPACE = "http://image.webservice";
private static final String URL = "http://10.0.2.2:8080/images?wsdl";
private static final String METHOD_NAME = "getImage";
private static final String SOAP_ACTION = "http://image.webservice/getImage";
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.setOutputSoapObject(request);
HttpTransportSE androidHttpTransport = new HttpTransportSE(URL);
try {
androidHttpTransport.call(SOAP_ACTION, envelope);
SoapPrimitive resultsRequestSOAP = (SoapPrimitive) envelope.getResponse();
String result = resultsRequestSOAP.toString();
if (result != "") {
byte[] bloc = Base64.decode(result, Base64.DEFAULT);
Bitmap bmp = BitmapFactory.decodeByteArray(bloc,0,bloc.length);
ImageView image = new ImageView(this);
image.setImageBitmap(bmp);
setContentView(image);
}
} catch (Exception e) {
System.out.println("******* THERE WAS AN ERROR ACCESSING THE WEB SERVICE");
e.printStackTrace();
}
}
}
我希望这对可能需要它的其他人有用。您还必须设置权限:
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
。另请注意,仿真器在10.0.2.2上连接到计算机的localhost,而不是127.0.0.1
答案 1 :(得分:5)
您似乎错过了一个重要的解码步骤。生成SOAP响应的代码必须对字节数组进行编码,以便它可以表示为XML中的字符串。如果不知道服务器端使用的编码机制(base64, etc.),很难说你应该如何解码它。
在上面的代码中,您调用String#getBytes(),它使用默认字符集(在Android上为UTF-8)将给定字符串编码为二进制数据。这与解码原始图像数据不同。 UTF-8不能用作通用编码机制,因为它不能表示任意字节序列(并非所有字节序列都是有效的UTF-8)。
检查服务代码以查看它如何编码二进制数据并在客户端使用适当的解码机制,它应该可以解决您的问题。
HTH。
编辑:This faq(对于旧版本但可能仍然适用)建议将字节数组编码为base64并将其包装在SoapPrimitive中。我个人会使用Commons Codec及其Base64类将字节数组编码为服务器端的字符串,并在客户端使用它将此字符串解码回原始字节数组。
需要注意的一件事...... Android实际上捆绑了旧版本的Commons Codec,这样可能会让你失望。特别是它不包括encodeBase64String
便利方法,因此您需要进行实验或进行一些研究,以找出Android平台上存在哪些解码方法。您可以在客户端使用android.util.Base64,但请确保使用与您在服务器端使用的编码样式匹配的正确标志。祝你好运。
答案 2 :(得分:0)
我们需要在发送字节数组之前实现序列化,否则我们得到错误无法序列化字节数组。见下面的例子
private static final String NAMESPACE = ".xsd url taken from the web service URL";
private static final String URL = "web service URL";
private static final String SOAP_ACTION = "Action port typr";
private static final String METHOD_NAME = "Method name";
the above parameter can be taken from the users web service (?WSDL) url
SoapObject request = new SoapObject(NAMESPACE, AUTH_METHOD);
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(
SoapEnvelope.VER11);
new MarshalBase64().register(envelope); //serialization
envelope.encodingStyle = SoapEnvelope.ENC;
request.addProperty("body", str);
request.addProperty("image", imagebyte);
envelope.setOutputSoapObject(request);
HttpTransportSE androidHttpTransport = new HttpTransportSE(URL);
try{
androidHttpTransport.call(SOAP_ACTION, envelope);
SoapObject resultsRequestSOAP = (SoapObject) envelope.bodyIn;
String str=resultsRequestSOAP.toString();
}catch(Exception e)
{
}
see