2015-08-21 52 views
3

我目前正在建立一個Android應用程序,但我遇到了一個問題。 我用Java和Jersey創建了後端部分(託管在服務器上)。發送mulipart /表單數據請求中的Android

我所有的Web服務是POST,並返回一個JSON字符串和幾乎所有的人只需要字符串,但其中幾個也需要接收文件。

  • 當我使用Google Postman調用Web服務時,一切正常。
  • 當我送從我的Android項目,我創建(另一個項目)的PHP文件POST請求,它也能正常工作。

但是,當我嘗試向我的Web服務發送請求時,我遇到啓動Android應用程序的錯誤。根據內容類型,響應代碼可以是415或500。

我的問題是,我應該怎麼設置在兩側的內容類型從Android發送POST請求到我的服務器,並得到一個JSON字符串?我需要補充一點,我有時還需要通過POST請求發送文件。

這是我在我的Java代碼

@POST 
@Path("/login") 
@Consumes("multipart/form-data") 

public String getLogin(@FormDataParam("mail") String mail, 
     @FormDataParam("pwd") String pwd){ ... 

而這就是我在我的Android代碼

HttpURLConnection con = (HttpURLConnection) url.openConnection(); 
con.setRequestMethod(p.getMethod()); 
con.setRequestProperty("Content-type", "multipart/form-data"); 

預先感謝您。

回答

0

嘗試兩側Content-Type設置爲application/json。也就是說,如果你發送一個JSON字符串到服務器。如果您要發送的文件是文本文件,請使用application/text。否則,請查看here以獲取有關不同文件格式的正確Content-Type的信息。

+0

謝謝你的回答,但是,我編程的服務器,以便我期望作爲輸入值是一個鍵和值的列表。完全像在GET請求中一樣,您添加(鍵值)對。我的問題是如何將這種類型的數據發送到Java服務器 – marcsarfa

0

試圖格式化multipart請求不是一個簡單的任務,如果你不知道你在做什麼。你可以看到W3C documentation一個樣本格式和一些解釋

Content-Type: multipart/form-data; boundary=AaB03x 

    --AaB03x 
    Content-Disposition: form-data; name="submit-name" 

    Larry 
    --AaB03x 
    Content-Disposition: form-data; name="files"; filename="file1.txt" 
    Content-Type: text/plain 

    ... contents of file1.txt ... 
    --AaB03x-- 

這幾乎是身體(和Content-Type頭)應該是什麼時,你的請求等。我做了簡單的幫助類,適用於簡單的String和文件情況。這並不需要太長時間,我也沒有經過測試,但它適用於簡單的用例。就我個人而言,我可能會做一些重構,但它會給你一個起點。

import java.io.BufferedWriter; 
import java.io.File; 
import java.io.FileInputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.OutputStream; 
import java.io.OutputStreamWriter; 
import java.io.Writer; 
import java.net.HttpURLConnection; 
import java.util.ArrayList; 
import java.util.List; 

public class MultipartHelper { 

    public String contentType; 
    public String boundary; 
    public HttpURLConnection connection; 

    private final List<FilePart> fileParts = new ArrayList<>(); 
    private final List<StringPart> stringParts = new ArrayList<>(); 

    public MultipartHelper(HttpURLConnection connection) throws IOException { 
     this(connection, "multipart/form-data"); 
    } 

    public MultipartHelper(HttpURLConnection connection, String contentType) throws IOException { 
     this.boundary = String.valueOf(System.currentTimeMillis()); 
     this.connection = connection; 
     contentType = contentType == null? "multipart/form-data": contentType; 
     contentType += "; boundary=" + boundary; 

     connection.setRequestProperty("Content-Type", contentType); 
    } 

    public void addStringPart(String data, String name) { 
     stringParts.add(new StringPart(data, name)); 
    } 

    public void addFilePart(File file, String contentType, String name) { 
     if (contentType == null) { 
      contentType = "application/octet-stream"; 
     } 
     fileParts.add(new FilePart(file, contentType, name)); 
    } 

    public void makeRequest() { 
     Writer writer = null; 
     try { 
      OutputStream out = connection.getOutputStream(); 
      writer = new BufferedWriter(new OutputStreamWriter(out)); 

      for (StringPart sp: stringParts) { 
       writer.write("--" + boundary + "\r\n"); 
       writer.write("Content-Disposition: form-data; name=" + sp.name + "\r\n"); 
       writer.write("Content-Type: text/plain\r\n\r\n"); 
       writer.write(sp.data + "\r\n"); 
      } 
      writer.flush(); 

      InputStream in = null; 
      for (FilePart fp: fileParts) { 
       writer.write("--" + boundary + "\r\n"); 
       writer.write("Content-Disposition: form-data; name=" 
         + fp.name + "; filename=" + fp.file.getName() + "\r\n"); 
       writer.write("Content-Type: " + fp.contentType + "\r\n\r\n"); 
       writer.flush(); 

       in = new FileInputStream(fp.file); 
       int count; 
       byte[] buffer = new byte[2048]; 
       while ((count = in.read(buffer)) != -1) { 
        out.write(buffer, 0, count); 
       } 
       out.flush(); 
       writer.write("\r\n"); 
       writer.flush(); 

       in.close(); 
      } 
      writer.write("--" + boundary + "--\r\r"); 
      writer.flush(); 
      out.close(); 
      writer.close(); 

     } catch (IOException ex) { 
      ex.printStackTrace(); 
     } 
    } 

    class StringPart { 
     String data; 
     String name; 
     public StringPart(String data, String name) { 
      this.data = data; 
      this.name = name; 
     } 
    } 

    class FilePart { 
     File file; 
     String name; 
     String contentType; 
     public FilePart(File file, String contentType, String name) { 
      this.file = file; 
      this.name = name; 
      this.contentType = contentType; 
     } 
    } 
} 

用法示例

final String urlStr = "http://localhost:8080/api/upload"; 
URL url = new URL(urlStr); 
HttpURLConnection connection = (HttpURLConnection)url.openConnection(
     new Proxy(Proxy.Type.HTTP, new InetSocketAddress("localhost", 8888))); 
connection.setDoInput(true); 
connection.setDoOutput(true); 
connection.setRequestMethod("POST"); 

MultipartHelper multipart = new MultipartHelper(connection); 
multipart.addStringPart("Hello Part 1", "string1"); 
multipart.addFilePart(new File("stackoverflow.png"), "image/png", "image"); 

multipart.makeRequest(); 

我個人雖然,我會去的已經有此功能的庫。例如Retrofit具有多部分支持。這是一個非常受歡迎的休息客戶端庫。這裏有一個例子

首先需要依賴

Maven的

<dependency> 
    <groupId>com.squareup.retrofit</groupId> 
    <artifactId>retrofit</artifactId> 
    <version>1.9.0</version> 
</dependency> 

搖籃

compile 'com.squareup.retrofit:retrofit:1.9.0' 

首先,你需要一個接口,爲客戶服務

import retrofit.http.Multipart; 
import retrofit.http.POST; 
import retrofit.http.Part; 
import retrofit.mime.TypedFile; 
import retrofit.mime.TypedString; 

public interface UploadService { 

    @Multipart 
    @POST("/upload") 
    retrofit.client.Response upload(@Part("image") TypedFile image, 
            @Part("string1") TypedString string1); 
} 

ŧ母雞使請求像

RestAdapter adapter = new RestAdapter.Builder() 
     .setLogLevel(RestAdapter.LogLevel.FULL) 
     .setEndpoint("http://localhost:8080/api") 
     .build(); 

UploadService service = adapter.create(UploadService.class); 
TypedFile file = new TypedFile("image/png", new File("stackoverflow.png")); 
TypedString str = new TypedString("Hello World"); 

retrofit.client.Response response = service.upload(file, str); 
相關問題