在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萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章