随笔 - 312, 文章 - 14, 评论 - 1393, 引用 - 0
数据加载中……

WebService大讲堂之Axis2(4):二进制文件传输

本文为原创,如需转载,请注明作者和出处,谢谢!

上一篇:
WebService大讲堂之Axis2(3):使用services.xml文件发布WebService 

    在《WebService大讲堂之Axis2(2):复合类型数据的传递》中讲过,如果要传递二进制文件(如图像、音频文件等),可以使用byte[]作为数据类型进行传递,然后客户端使用RPC方式进行调用。这样做只是其中的一种方法,除此之外,在客户端还可以使用wsdl2java命令生成相应的stub类来调用WebServicewsdl2java命令的用法详见《WebService大讲堂之Axis2(1):用POJO实现0配置的WebService》。
    WebService类中包含byte[]类型参数的方法在wsdl2java生成的stub类中对应的数据类型不再是byte[]类型,而是javax.activation.DataHandlerDataHandler类是专门用来映射WebService二进制类型的。
    在
WebService类中除了可以使用byte[]作为传输二进制的数据类型外,也可以使用javax.activation.DataHandler作为数据类型。 不管是使用byte[],还是使用javax.activation.DataHandler作为WebService方法的数据类型,使用wsdl2java命令生成的stub类中相应方法的类型都是javax.activation.DataHandler。而象使用.netdelphi生成的stub类的相应方法类型都是byte[]。这是由于javax.activation.DataHandler类是Java特有的,对于其他语言和技术来说,并不认识javax.activation.DataHandler类,因此,也只有使用最原始的byte[]了。
    下面是一个上传二进制文件的例子,
WebService类的代码如下:

package service;

import java.io.InputStream;
import java.io.OutputStream;
import java.io.FileOutputStream;
import javax.activation.DataHandler;

public class FileService
{
   
//  使用byte[]类型参数上传二进制文件
    public boolean uploadWithByte(byte[] file, String filename)
    {
         FileOutputStream fos 
= null;
         
try
         {                          
             fos 
= new FileOutputStream(filename);    
             fos.write(file);
             fos.close();
         }
         
catch (Exception e)
         {
             
return false;
         }
         
finally
         {
             
if (fos != null)
             {
                 
try
                 {
                     fos.close();
                 }
                 
catch (Exception e)
                 {
                 }
             }
         }
         
return true;
    }
    
private void writeInputStreamToFile(InputStream is, OutputStream os) throws Exception
    {
         
int n = 0;
         
byte[] buffer = new byte[8192];
         
while((n = is.read(buffer)) > 0)
         {
             os.write(buffer, 
0, n);
         }
    }
    
//  使用DataHandler类型参数上传文件
    public boolean uploadWithDataHandler(DataHandler file, String filename)
    {
        
         FileOutputStream fos 
= null;
         
try
         {            
             fos 
= new FileOutputStream(filename);   
             
//  可通过DataHandler类的getInputStream方法读取上传数据
             writeInputStreamToFile(file.getInputStream(), fos);
             fos.close();
         }
         
catch (Exception e)
         {
             
return false;
         }
         
finally
         {
             
if (fos != null)
             {
                 
try
                 {
                     fos.close();
                 }
                 
catch (Exception e)
                 {
                 }
             }
         }
         
return true;
    }
}

上面代码在services.xml文件的配置代码如下:

<service name="fileService">
    
<description>
        文件服务
    
</description>
    
<parameter name="ServiceClass">
        service.FileService 
    
</parameter>
        
<messageReceivers>
        
<messageReceiver mep="http://www.w3.org/2004/08/wsdl/in-out"
            class
="org.apache.axis2.rpc.receivers.RPCMessageReceiver" />
    
</messageReceivers>
</service>


    如果使用
wsdl2java命令生成调用Java客户端代码,则需要创建DataHandler类的对象实例,代码如下:

DataHandler dh = new DataHandler(new FileDataSource(imagePath));

wsdl2java命令会为每一个方法生成一个封装方法参数的类,类名为方法名(第一个字符大写),如uploadWithByte方法生成的类名为UploadWithByte。如果要设置file参数的值,可以使用UploadWithByte类的setFile方法,代码如下:


UploadWithByte uwb = new UPloadWithByte();
uwb.setFile(dh);

最后是调用uploadWithByte方法,代码如下(FileServiceStubwsdl2java生成的stub类名):


FileServiceStub fss = new FileServiceStub();
fss.uploadWithByte(uwb);

如果使用C#调用FileService,则file参数类型均为byte[],代码如下:

MemoryStream ms = new MemoryStream();
Bitmap bitmap 
= new Bitmap(picUpdateImage.Image);
bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
service.fileService fs 
= new WSC.service.fileService();
fs.uploadWithDataHandler(ms.ToArray());
fs.uploadWithByte(ms.ToArray());
 

其中picUpdateImagec#中加载图像文件的picturebox控件。

下一篇:
WebService大讲堂之Axis2(5):会话(Session)管理





Android开发完全讲义(第2版)(本书版权已输出到台湾)

http://product.dangdang.com/product.aspx?product_id=22741502



Android高薪之路:Android程序员面试宝典 http://book.360buy.com/10970314.html


新浪微博:http://t.sina.com.cn/androidguy   昵称:李宁_Lining

posted on 2009-01-22 10:28 银河使者 阅读(22444) 评论(18)  编辑  收藏 所属分类: java 原创webservice

评论

# re: WebService大讲堂之Axis2(4):二进制文件传输  回复  更多评论   

赞!
2009-01-23 22:25 | zuzong

# re: WebService大讲堂之Axis2(4):二进制文件传输  回复  更多评论   

支持!
2009-02-01 13:53 | BeanSoft

# re: WebService大讲堂之Axis2(4):二进制文件传输  回复  更多评论   

太好了!!支持!
2009-02-16 22:39 | 宋丙坤

# re: WebService大讲堂之Axis2(4):二进制文件传输  回复  更多评论   

sql查询的结果ResultSet,如何进行传输啊?
2009-03-30 14:20 | passerby

# re: WebService大讲堂之Axis2(4):二进制文件传输  回复  更多评论   

@passerby
webservice不支持ResultSet类型,一般将ResultSet中的数据放到对象数组中。如果你用hibernate这样的ORM就方便的多,这也是ORM的重要应用之一。
2009-03-30 14:26 | 银河使者

# re: WebService大讲堂之Axis2(4):二进制文件传输  回复  更多评论   

怎么没写客户端代码啊!
2009-05-18 09:30 |

# re: WebService大讲堂之Axis2(4):二进制文件传输  回复  更多评论   

后面有客户端代码
2009-05-18 12:44 | 银河使者

# re: WebService大讲堂之Axis2(4):二进制文件传输  回复  更多评论   

支持作者,不错不错,谢谢,很好啊。
2009-05-18 18:13 | Harold.Zhang

# re: WebService大讲堂之Axis2(4):二进制文件传输  回复  更多评论   

怎么没写客户端代码啊!
2009-10-19 16:48 | cjoy

# re: WebService大讲堂之Axis2(4):二进制文件传输  回复  更多评论   

多谢作者辛勤劳动~~
能不能写一个 axis2、MySQL、web技术 结合的例子呀?
2009-10-23 20:17 | lce

# re: WebService大讲堂之Axis2(4):二进制文件传输  回复  更多评论   

好文章,谢谢了,请问下我做了个从别人服务器下载文件,以byte[]进行传输,为什么文件超过10M就报内存溢出呢?
2009-10-31 08:53 | zsy

# re: WebService大讲堂之Axis2(4):二进制文件传输  回复  更多评论   

当然会报错,是因为超过了java允许的数组长度,下载大文件最好直接用http,不用webservice。webservice是用来传数据的,不是用来下文件的。
2009-10-31 20:57 | 银河使者

# re: WebService大讲堂之Axis2(4):二进制文件传输 2009-03-30 14:26 银河使者   回复  更多评论   

@银河使者
建议客户端代码我想作者还是不要给出的好。首先,客户端代码的两种书写方式作者在上文都有介绍,而且无论是用wsdl2java命令生成客户端代码还是直接用RPC方式书写客户端代码,都需要我们在自己的机器上亲自动手操作一遍才能印象深刻,在这个过程中,几乎都会报出各种各样的错误,那么解决这一个个的错误是不是就是给读者一个很好的学习过程呢?
2009-11-02 17:33 | Mr.Blue

# re: WebService大讲堂之Axis2(4):二进制文件传输  回复  更多评论   

我自己做了个客户端
RPCServiceClient serviceClient = new RPCServiceClient();
Options options = serviceClient.getOptions();
EndpointReference targetEPR = new EndpointReference("http://localhost:8080/axis2/services/fileService");
options.setTo(targetEPR);
// 下面的代码调用uploadImageWithByte方法上传图像文件
/////////////////////////////////////////
// 打开图像文件,确定图像文件的大小
java.io.File file = new java.io.File("f:\\images.jpg");
java.io.FileInputStream fis = new java.io.FileInputStream("f:\\31.txt");
// 创建保存要上传的图像文件内容的字节数组
byte[] buffer = new byte[(int) file.length()];
// 将图像文件的内容读取buffer数组中
int n = fis.read(buffer);
System.out.println("文件长度:" + file.length());
Object[] opAddEntryArgs = new Object[]{ buffer,"d:\\31.txt" };
Class[] classes = new Class[]{ Boolean.class };
QName opAddEntry = new QName("http://ws.apache.org/axis2","uploadWithByte"" target="_new" rel="nofollow">http://ws.apache.org/axis2","uploadWithByte");
fis.close();
// 开始上传图像文件,并输出uploadWithByte方法的返回传
System.out.println(serviceClient.invokeBlocking(opAddEntry,opAddEntryArgs, classes)[0]);
但是报错:
Exception in thread "main" org.apache.axis2.AxisFault: namespace mismatch require http://service found http://ws.apache.org/axis2
at org.apache.axis2.util.Utils.getInboundFaultFromMessageContext(Utils.java:512)
at org.apache.axis2.description.OutInAxisOperationClient.handleResponse(OutInAxisOperation.java:370)
at org.apache.axis2.description.OutInAxisOperationClient.send(OutInAxisOperation.java:416)
at org.apache.axis2.description.OutInAxisOperationClient.executeImpl(OutInAxisOperation.java:228)
at org.apache.axis2.client.OperationClient.execute(OperationClient.java:163)
at org.apache.axis2.client.ServiceClient.sendReceive(ServiceClient.java:548)
at org.apache.axis2.client.ServiceClient.sendReceive(ServiceClient.java:528)
at org.apache.axis2.rpc.client.RPCServiceClient.invokeBlocking(RPCServiceClient.java:102)
at client.FileServiceClient.main(FileServiceClient.java:36)

2009-11-11 00:17 | 茶杯里的叶子

# re: WebService大讲堂之Axis2(4):二进制文件传输  回复  更多评论   

写的不错,非常感谢
2009-11-28 13:24 | SkyStar

# re: WebService大讲堂之Axis2(4):二进制文件传输  回复  更多评论   

做了个DataHandler的client端代码
RPCServiceClient serviceClient = new RPCServiceClient();
Options options = serviceClient.getOptions();
EndpointReference targetEPR = new EndpointReference("http://localhost:8080/axis2/services/fileService");
options.setTo(targetEPR);
DataHandler dh = new DataHandler(new FileDataSource("e:/Sunset.jpg"));
Object[] opAddEntryArgs = new Object[]{ dh,"e:/fun.jpg" };
Class[] classes = new Class[]{ Boolean.class };
QName opAddEntry = new QName("http://service","uploadWithDataHandler");
System.out.println(serviceClient.invokeBlocking(opAddEntry, opAddEntryArgs,classes)[0]);
2011-12-14 11:47 | funfenffun

# re: WebService大讲堂之Axis2(4):二进制文件传输[未登录]  回复  更多评论   

楼主,如何从DataHandler中取出序列化的对象?我这样取报错
DataHandler dh=stub.getUserBytes(gub).get_return();
ObjectInputStream ois=new ObjectInputStream(dh.getInputStream());
User u2=(User)ois.readObject();
报错: java.lang.ClassCastException
2012-07-26 16:56 | freefish

# re: WebService大讲堂之Axis2(4):二进制文件传输  回复  更多评论   

你好,我不进行上传文件操作,只是客户端调用服务端方法时需要一个byte[]类型的参数,在axis2里可以直接写参数,
Object[] opAddEntryArgs = new Object[] {xmlDataByte};
在xfire里
Object[] result = client.invoke("test", new Object[]{xmlDataByte});
这个xmlDataByte就是byte[]数组类型,会报错
[B cannot be cast to javax.activation.DataHandler

我不用wsdl2java的自动生产代码模式,请问有什么解决方案吗?
2013-05-08 00:06 | hl

只有注册用户登录后才能发表评论。


网站导航: