2010-11-03 61 views
2

我休息web服務,需要一個POST梅託德與多消息:的HttpClient和MultipartEntity主場迎戰新澤西多部分和Android

@Path("transferFile")  
@POST 
@Consumes(MediaType.MULTIPART_FORM_DATA) 
@Produces(MediaType.APPLICATION_XML) 
public String multipartTest(com.sun.jersey.multipart.MultiPart data) { 
try { 
// get first body part (index 0)   
BodyPart bp = multiPart.getBodyParts().get(0); 
etc.. 

現在我嘗試寫一個Java客戶端。我從一個簡單的球衣客戶端開始: view plaincopy to clipboardprint?

MultiPart multiPart = new MultiPart(); 
    multiPart.bodyPart(new BodyPart(wavestream,MediaType.APPLICATION_OCTET_STREAM_TYPE)); 

    Client c = Client.create(); 
    WebResource r = c.resource("http://127.0.0.1:8080/webapp:); 
response=r.path("transferFile").type(MediaType.MULTIPART_FORM_DATA).accept(MediaType.APPLICATION_XML).post(String.class, multiPart); 

這很好用 - 一切正常。不過,我需要這個客戶端在Android上工作,並且在該平臺上使用球衣時遇到了麻煩。所以我用正常的方式在Android上發送多消息:

HttpClient client = new DefaultHttpClient(); 
client.getParams().setParameter("http.socket.timeout", new Integer(90000)); // 90 second 

HttpPost httpPost = new HttpPost("http://127.0.0.1:8080/webapp/transferFile"); 
httpPost.setHeader("Content-Type", MediaType.MULTIPART_FORM_DATA); 

//tried with and without base64 
byte [] encodedWavestream = Base64.encodeBytesToBytes(wavestream); 
InputStream ins = new ByteArrayInputStream(encodedWavestream); 
InputStreamBody body = new InputStreamBody(ins, "test"); 
int send = ins.available(); 

MultipartEntity requestContent = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE); 
requestContent.addPart("stream", body); 

httpPost.setEntity(requestContent); 
HttpResponse Response = client.execute(httpPost); 

的這給來自服務器的響應煩人:

HTTP Status 400 - Bad Request 
The request sent by the client was syntactically incorrect (Bad Request). 

我檢查服務器日誌文件,但裏面空空如也。所以我不知道這個錯誤的起源是什麼。我寫了一個簡單的HTML頁面,其中包含一個公式和'multipart/form-data'內容類型,它也可以工作!從soapUI自動生成的請求也適用!爲什麼我的客戶不工作?任何人都可以幫忙嗎?

+0

我假設你正在使用的Android仿真器和應用程序服務器位於同一主機上。在這種情況下,您必須使用10.0.2.2而不是本地主機或127.0.0.1來訪問主機系統!否則,你指向虛擬(模擬)設備本身。 – Lars 2012-08-16 20:32:32

回答

1

澤西島有蟲子。請參閱Chunked encoding problem

此問題僅適用於少數客戶(iOS,Android)。

如果將Content-Type設置爲application/octet-stream,則應用程序/ octet-stream的Jersey MessageWriter將設置Content-Length,並且不會將其作爲分塊傳輸方法發送。

solution爲Jersey客戶端:

ClientConfig config = new DefaultClientConfig(); 
config.getProperties().put(ClientConfig.PROPERTY_CHUNKED_ENCODING_SIZE, 32 * 1024); 

但它不會爲iOS版的或Android的客戶端工作。 所以我測試了Apache文件上傳。 Threre是另一個錯誤:「流意外結束了」。

只有Oreilly upload可以上傳文件正確的所有客戶端。 這是我的代碼:

public Object[] getParametersAndFiles(HttpServletRequest request) throws IOException { 
    log.debug("OreillyUpload"); 
    Properties params = new Properties(); 
    LinkedHashMap files = new LinkedHashMap(); 

    File tempDirectory = new File(System.getProperty("java.io.tmpdir")); 

    MultipartParser mp = new MultipartParser(request, 1*1024*1024); // 10MB 
    Part part; 
    while ((part = mp.readNextPart()) != null) { 
     String name = part.getName(); 
     if (part.isParam()) { 
      // it's a parameter part 
      ParamPart paramPart = (ParamPart) part; 
      String value = paramPart.getStringValue(); 
      params.put(name, value); 

      log.debug("param; name=" + name + ", value=" + value); 
     } 
     else if (part.isFile()) { 
      // it's a file part 
      FilePart filePart = (FilePart) part; 
      String fileName = filePart.getFileName(); 
      if (fileName != null) { 
       // the part actually contained a file 
       File file = new File(tempDirectory,fileName); 
       long size = filePart.writeTo(file); 
       files.put(name, file); 

       log.debug("file; name=" + name + "; filename=" + fileName + 
         ", filePath=" + filePart.getFilePath() + 
         ", content type=" + filePart.getContentType() + 
         ", size=" + size); 

      } 
      else { 
       // the field did not contain a file 
       log.debug("file; name=" + name + "; EMPTY"); 
      } 
     } 
    } 

    return new Object[] {params, files}; 
} 

這是澤西Server代碼(警告所有澤西上傳anotations(如爲 「@FormDataParam」)應該被刪除):

@POST 
@Path("uploadMarkup") 
@Produces(MediaType.APPLICATION_JSON) 
// @Consumes(MediaType.MULTIPART_FORM_DATA) 
//// public void uploadMarkup(
// public JSONWithPadding uploadMarkup(
//   @FormDataParam("markupFile") InputStream markupFile, 
//   @FormDataParam("markupFile") FormDataContentDisposition details, 
//   @FormDataParam("slideNum") int slideNum) { 
public JSONWithPadding uploadMarkup(@Context HttpServletRequest request) { 
    Object[] data = uploadService.getParametersAndFiles(request); 
    ... 
} 
相關問題