webservice傳輸檔案

i_wanna_rock發表於2017-12-19

1. 通過webservice上傳檔案的原理

我們都知道如何通過WebService把一個字串形式的引數傳遞到伺服器端的一個函式並取得返回的結果,而通過WebService上傳檔案的原理和上傳一個字串在根本上是一樣的。
唯一不同的是,我們需要多做一點額外的工作,即先讀取檔案到一個位元組陣列中,再通過Base64將其轉化為字串。詳情請看下面的程式碼:
// 客戶端讀取檔案然後用Base64將其轉化為字串的函式
private static String getFileByteString(File file) throws Exception{
InputStream in = new FileInputStream(file);

// 取得檔案大小
long length = file.length();

// 根據大小建立位元組陣列
byte[] bytes = new byte[(int) length];

// 讀取檔案內容到位元組陣列
int offset = 0;
int numRead = 0;
while (offset < bytes.length
    && (numRead = in.read(bytes, offset, bytes.length - offset)) >= 0) {
  offset += numRead;
}

// 讀取完畢的校驗  
if (offset < bytes.length) {
  throw new IOException("不能完全讀取檔案:"+ file.getName());
}

in.close();

String encodedFileString = Base64.encode(bytes);

return encodedFileString;

}

伺服器端如何將接收到的字串還原成檔案
有了上頁函式的幫助,我相信你將它傳遞到WebSercvice端某函式是必能做到的事,剩下的問題是,如何將接收到的字串還原成檔案呢?
答案是再用Base64將字串還原成位元組陣列再將它寫入一個檔案即可,這樣寫出來的檔案能保證內容和你上傳的原檔案一致,下面是示例程式:

WebService伺服器端將接收來的字串還原的檔案的過程
// uploadedFileString是傳過來的包含你上傳的檔案內容的字串
byte[] bytes = Base64.decode(uploadedFileString);

// 儲存路徑
String path=CommonUtil.getUploadPath();

// 儲存的檔名
String localFileName=getLocalFileName(parser.getUserid(),parser.getFileName());

// 寫入新檔案
FileOutputStream out = new FileOutputStream(path+localFileName);
out.write(bytes);
out.flush();
out.close();

客戶端如何訪問已上傳的檔案

上傳只是手段,我們上傳的真正目的其實是下載,就我們剛才上傳的檔案而言,如何能讓人訪問到它呢?我們可以如下辦理:
1.將上傳檔案書寫在WebService所在Web應用下的某目錄中,如upload”1.jpg,這樣客戶就可以通過這樣的URL訪問到這個檔案http://209.205.177.42:8080/webApp/upload/1.jpg. 上面IP地址是WebSercice應用所在機器的公網地址,webApp是該應用名。
2.在客戶端上傳檔案完畢後,將上述地址以函式返回值的形式告知客戶,客戶就可以通過網路來訪問它了。

如何得到WebApp下的upload目錄
書寫一個在WebApp啟動時就啟動的Servlet,在其init函式就能得知Webapp所在目錄,得到upload目錄再往下走一層就行了。下面的InitServlet的示例程式碼:
public class InitialSystemServlet extends HttpServlet {

private static final long serialVersionUID = -7444606086930580188L;

public void doPost(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, java.io.IOException {
}

public void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, java.io.IOException {
    doPost(request, response);
}

public void init(ServletConfig config) throws ServletException {

    // 設定上傳路徑
    CommonUtil.setUploadPath(config.getServletContext().getRealPath("/"));
}

}

其它問題
1.如何防止檔案被覆蓋:在生成檔案時採用時間+使用者ID+隨機數的檔名,這樣重名機率就大大降低,還不放心可以在寫檔案之間檢驗檔案是否已存在了。
2.如何要把檔案不放在伺服器而是放到資料庫怎麼辦:你可以把檔案內容甚至字串直接儲存到資料庫,需要下載時再取出來。

2. webservice二進位制檔案傳輸

最近boss要求做android客戶端的圖片上傳和下載,就是呼叫伺服器的webservice介面,實現從android上傳圖片到伺服器,然後從伺服器下載圖片到android客戶端。
需求下來了,開始動腦筋了唄。
通常,我們呼叫webservice,就是伺服器和客戶端(瀏覽器,android手機端等)之間的通訊,其通訊一般是傳 xml或json格式的字串。對,就只能是字串。
我的思路是這樣的,從android端用io流讀取到要上傳的圖片,用Base64編碼成位元組流的字串,通過呼叫webservice把該字串作為引數傳到伺服器端,服務端解碼該字串,最後儲存到相應的路徑下。整個上傳過程的關鍵就是 以 位元組流的字串 進行資料傳遞。下載過程,與上傳過程相反,把伺服器端和客戶端的程式碼相應的調換。
不羅嗦那麼多,上程式碼。流程是:把android的sdcard上某張圖片 上傳到 伺服器下images 資料夾下。
注:這只是個demo,沒有UI介面,檔案路徑和檔名都已經寫死,執行時,相應改一下就行。
1 。讀取android sdcard上的圖片。
public void testUpload(){
try{
String srcUrl = “/sdcard/”; //路徑
String fileName = “aa.jpg”; //檔名
FileInputStream fis = new FileInputStream(srcUrl + fileName);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int count = 0;
while((count = fis.read(buffer)) >= 0){
baos.write(buffer, 0, count);
}
String uploadBuffer = new String(Base64.encode(baos.toByteArray())); //進行Base64編碼
String methodName = “uploadImage”;
connectWebService(methodName,fileName, uploadBuffer); //呼叫webservice
Log.i(“connectWebService”, “start”);
fis.close();
}catch(Exception e){
e.printStackTrace();
}
}
connectWebService()方法:
//使用 ksoap2 呼叫webservice
private boolean connectWebService(String methodName,String fileName, String imageBuffer) {
String namespace = “http://134.192.44.105:8080/SSH2/service/IService“; // 名稱空間,即伺服器端得介面,注:字尾沒加 .wsdl,
//伺服器端我是用x-fire實現webservice介面的
String url = “http://134.192.44.105:8080/SSH2/service/IService“; //對應的url
//以下就是 呼叫過程了,不明白的話 請看相關webservice文件
SoapObject soapObject = new SoapObject(namespace, methodName);
soapObject.addProperty(“filename”, fileName); //引數1 圖片名
soapObject.addProperty(“image”, imageBuffer); //引數2 圖片字串
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(
SoapEnvelope.VER10);
envelope.dotNet = false;
envelope.setOutputSoapObject(soapObject);
HttpTransportSE httpTranstation = new HttpTransportSE(url);
try {
httpTranstation.call(namespace, envelope);
Object result = envelope.getResponse();
Log.i(“connectWebService”, result.toString());
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
2。 伺服器端的webservice程式碼 :
public String uploadImage(String filename, String image) {
FileOutputStream fos = null;
try{
String toDir = “C:\Program Files\Tomcat 6.0\webapps\SSH2\images”; //儲存路徑
byte[] buffer = new BASE64Decoder().decodeBuffer(image); //對android傳過來的圖片字串進行解碼
File destDir = new File(toDir);
if(!destDir.exists()) destDir.mkdir();
fos = new FileOutputStream(new File(destDir,filename)); //儲存圖片
fos.write(buffer);
fos.flush();
fos.close();
return “上傳圖片成功!” + “圖片路徑為:” + toDir;
}catch (Exception e){
e.printStackTrace();
}
return “上傳圖片失敗!”;
}
對android 端進行 單元測試呼叫testUpload()方法,如果你看到綠條的話,說明呼叫成功!在伺服器下,就可以看到你上傳的圖片了。。。。
當然,這個demo很簡陋,沒有漂亮UI什麼的,但是這是 android端呼叫webservice進行上傳圖片的過程。從伺服器下載到android端,道理亦然。歡迎大家交流學習。。。。

相關文章