在axis中实现附件上传

通过SOAP传送文件,最简单的方式就是将数据先进行Base64编码,这对于数据量小的文件来说是一个不错的解决方案,同时实现起来也比较方便.然后Base64编码有其局限性,经过编码后的数据要比原文多1/3的数据量,如果数据量较大的话,就要仔细斟酌一下了.
当然也可以考虑采用其他的传输协议,如FTP,这样就要考虑其他方面的问题,如防火墙等安全设置,系统之间的协调.
目前通过SOAP传送附件的标准有SWA(SOAP with Attachement,proposed by Microsoft and HP Labs),DIME(proposed by Microsoft)
Apache Axis目前两种标准都支持,通过SOAP传送附件,不但需要Axis的核心类库,还需要activation.jar和mail.jar,这两个jar用来支持Java MIME.没有这两个jar时,Axis可以正常工作,但不支持附件,使用时会报出 Attachment not support的异常.

Axis1.4发布在tomcat5.0.28上,Web服务服务器端程序:


import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

import javax.activation.DataHandler;
import javax.activation.FileDataSource;

import org.apache.log4j.Logger;

public class FileService{
 static Logger logger = Logger.getLogger(FileService.class.getName());
  public static String Repository="../uploads/";
  public String putFile(DataHandler dh,String name){
   if(name==null)
       name="test.tmp";
       logger.debug("文件名为空,设置文件名");
   try{
    File dir=new File(Repository);
    if(!dir.exists()){
         dir.mkdir();
         logger.debug("附件存放目录为空,创建 uploads 目录");
      }
    InputStream input=dh.getInputStream();
    FileOutputStream fos=new FileOutputStream(new File(dir,name));
    byte[] buffer=new byte[1024*4];
    int n=0;
    while((n=input.read(buffer))!=-1){
     fos.write(buffer,0,n);
     }
    input.close();
    fos.close();
   }catch(IOException e){
    e.printStackTrace();
   }
  return name+"send OK";
 }
 public DataHandler getFile(String name){
  File dir=new File(Repository);
  if(!dir.exists())
  dir.mkdir();
  File data=new File(dir,name);
  if(data.exists())
         return new DataHandler(new FileDataSource(data));
  else
         return null;
  }
}

 部署描述文件:

<deployment xmlns="http://xml.apache.org/axis/wsdd/" xmlns:java="http://xml.apache.org/axis/wsdd/providers/java" xmlns:ns1="urn:functions">
 
  <service name="FileService" provider="java:RPC">
    <parameter name="className" value="com.tsimgsong.pub.FileService"/>
    <parameter name="allowedMethods" value="*"/>
   
    <operation name="getFile" returnQName="returnqname" returnType="ns1:DataHandler" xmlns:SchemaNS="http://www.w3.org/2001/XMlSchema">
      <parameter name="name" type="SchemaNS:string"/>
    </operation>
   
    <operation name="putFile" returnQName="returnqname" returnType="ns1:DataHandler" xmlns:SchemaNS="http://www.w3.org/2001/XMlSchema">
      <parameter name="dh" type="ns1:DataHandler"/>
      <parameter name="name" type="SchemaNS:string"/>
    </operation>
   
   <typeMapping deserializer="org.apache.axis.encoding.ser.JAFDataHandlerDeserializerFactory"
                languageSpecificType="java:javax.activation.DataHandler" qname="ns1:DataHandler"
                serializer="org.apache.axis.encoding.ser.JAFDataHandlerSerializerFactory"
                encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
     
  </service>
 
</deployment>

客户端测试程序:

文件上传

public PutFile(String fileName) {
  this.fileName = fileName;
 }

 public boolean doPut() {
  return doPut(fileName);
 }

 public static boolean doPut(String fileName) {
  String name = GenerateFileName();
  try {
   Service service = new Service();
   Call call = (Call) service.createCall();
   DataHandler dh = new DataHandler(new FileDataSource(fileName));
   call.setTargetEndpointAddress(new java.net.URL(endpoint));
   call.setOperationName(new QName(endpoint, "putFile"));
   QName qnameattachment = new QName("FileService", "DataHandler");
   call.registerTypeMapping(dh.getClass(), qnameattachment,
     JAFDataHandlerSerializerFactory.class,
     JAFDataHandlerDeserializerFactory.class);
   call.addParameter("s1", qnameattachment, ParameterMode.IN);
   call.addParameter("s2", XMLType.XSD_STRING, ParameterMode.IN);
   call.setReturnType(XMLType.XSD_STRING);
   String uploadedFN = (String) call.invoke(new Object[] { dh, name });
   if (uploadedFN != null && uploadedFN.trim().length() > 0) {
    return true;
   }
  } catch (Exception e) {
   logger.error("调用文件上传Web服务出错:" + e.getMessage());
   return false;
  }
  return false;
 }

文件下载:

public GetFile(String fileName) {
  this.fileName = fileName;
 }

 public boolean doGet() {
  return doGet(fileName);
 }

 public static boolean doGet(String fileName) {
  InputStreamReader ins = null;
  BufferedReader br = null;
  FileWriter fw = null;
  
  try {
   Service service = new Service();
   Call call = (Call) service.createCall();
   DataHandler dh = new DataHandler(new FileDataSource(fileName));   
   call.setTargetEndpointAddress(new java.net.URL(endpoint));
   call.setOperationName(new QName(endpoint, "getFile"));
   QName qnameattachment = new QName("FileService", "DataHandler");
   call.registerTypeMapping(dh.getClass(), qnameattachment,
     JAFDataHandlerSerializerFactory.class,
     JAFDataHandlerDeserializerFactory.class);
   call.addParameter("s1", qnameattachment, ParameterMode.IN);
   
   call.setReturnType(new QName("FileService", "DataHandler"),DataHandler.class);
   DataHandler ret = (DataHandler) call.invoke(new Object[] { fileName });
   ins = new InputStreamReader(ret.getInputStream());
   br = new BufferedReader(ins);
    File dir=new File("DownLoadFile");
       if(!dir.exists()){
            dir.mkdir();
            logger.debug("下载文件存放目录不存在,创建 【"+dir.getAbsolutePath()+" 】目录");
         }
   File f = new File(dir,fileName+"_reply");
   fw = new FileWriter(f);
   String tmp = br.readLine();
   while(tmp!=null){
    fw.write(tmp+"/n");
    tmp = br.readLine();
   }
  } catch (Exception e) {
   logger.error("调用文件下载Web服务出错:" + e.getMessage());
   return false;
  }finally{
   try{
    br.close();
    ins.close();
    fw.close();
   }catch(Exception ee){
    
   }
  }
  return false;
 }
 

需要注意的地方:

在服务器端和客户端需要配置好相应的Classpath,在classpath中需要增加两个jar:activation.jar和mail.jar.同时,如果你将tomcat的日志登记调整到info或者debug,在部署这个Web服务时中间会抛出一些异常信息,这是正常情况,在axis.jar中,程序在JAFDataHandlerDeserializerFactory.create方法没有找到时,会有两外的处理方式,这只是作为一个Debug信息输出.

发布了28 篇原创文章 · 获赞 0 · 访问量 7万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章