2014-10-27 143 views
1

我試圖從Android應用內向我的Google App Engine應用發送POST請求,以便將文件上傳到blobstore並將一些元數據上傳到數據存儲。我構建了一個可以從瀏覽器訪問的常規Web表單,並從這裏發佈就可以正常工作。不過,我還沒有能夠從我的Android應用程序做同樣的事情。Android HttpPost請求無法發佈

很多其他的StackOverflow帖子都提到使用MultipartEntityMultipartEntityBuilder來構建發佈請求。前者似乎被棄用,但也有它的更多的例子,所以我嘗試了兩種方式(分別,當然):

HttpClient httpClient = new DefaultHttpClient(); 
HttpPost postRequest = new HttpPost(upload_url); 
MultipartEntityBuilder builder = MultipartEntityBuilder.create(); 
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE); 
builder.addTextBody("poem_name", "Testing poem_name from Android", ContentType.MULTIPART_FORM_DATA); 
builder.addTextBody("poem_text", "blah", ContentType.MULTIPART_FORM_DATA); 
postRequest.setEntity(builder.build()); 
HttpResponse response = httpClient.execute(postRequest); 
HttpEntity theEntity = response.getEntity(); 
theEntity.consumeContent(); 
httpClient.getConnectionManager().shutdown(); 

HttpClient httpClient = new DefaultHttpClient();  
HttpPost postRequest = new HttpPost(upload_url);       
StringBody poem_name = new StringBody("Testing poem_name from Android"); 
StringBody poem_text = new StringBody("blah"); 
MultipartEntity entity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE); 
entity.addPart("poem_name", poem_name); 
entity.addPart("poem_text", poem_text); 
postRequest.setEntity(entity); 
HttpResponse response = httpClient.execute(postRequest); 

原來的網頁表單,它就像一個魅力從一個普通瀏覽器,看起來像這樣在我的模板(我最初省略了Android代碼的文件上傳,作爲weas問題太多調試馬上):

<form action="{{ upload_url }}" method="POST" enctype="multipart/form-data"> 
    Poem Title: <input name="poem_name" required><br> 
    Poem Text:<br><textarea name="poem_text" rows="5" cols="40"></textarea><br> 
    Upload File: <input type="file" name="file"><br> 
    <input type="submit" name="submit" value="Add Poem"> 
</form> 

然而,當我既可以執行我的Android應用程序的前兩部分代碼中,沒有任何內容顯示在我的服務器上。傳遞到HttpPost構造函數的upload_url與在Web表單{{ upload_url }}(它是由Google App Engine動態生成的)的操作字段中使用的相同。所以,我想我會嘗試發佈到任何Web表單,而不是需要多部分實體和動態URL的表單。我建立了一個新的準系統Web表單應用程序的不同的頁面上,是這樣的...

<form action="/testForm" method="post"> 
    <input name="nickname"><br> 
    <input type="submit" value="Create Test Entity"> 
</form> 

...並嘗試了基本要求後所看到的衆多初學者的例子:

HttpClient httpClient = new DefaultHttpClient();  
HttpPost postRequest = new HttpPost("http://my-app-title.appspot.com/testForm"); 
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(1); 
nameValuePairs.add(new BasicNameValuePair("nickname", "test with NameValuePair")); 
postRequest.setEntity(new UrlEncodedFormEntity(nameValuePairs)); 
HttpResponse response = httpClient.execute(postRequest); 

果然,這個表單在瀏覽器中效果很好,但是在我的Android應用程序中執行此代碼時不會產生任何結果(甚至不會使用空值代替「暱稱」字段,這會告訴我問題在於發佈的請求未得到執行因爲某些原因)。根據我讀過的所有帳戶,這應該是有效的。有什麼我忘記了哪些不允許我完成發佈請求?我非常感謝任何幫助。

+0

您是否考慮查看響應以查看服務器是否有關於您的請求的任何內容? – njzk2 2014-10-27 21:22:10

+0

還是在android側的日誌中有什麼?你是否捕獲異常並且不記錄它們? – njzk2 2014-10-27 21:23:10

+0

嗨njzk2,謝謝你的回覆!看看實際的httpresponse證明是非常有用的。我會很快打出答案。 – Pete 2014-10-27 21:57:54

回答

1

根據njzk2的建議,我使用了InputStream來查看HttpResponse的內容。作爲參考,這是我使用的代碼:

InputStream iStream = response.getEntity().getContent(); 
BufferedReader reader = new BufferedReader(new InputStreamReader(iStream)); 
while ((tempString = reader.readLine()) != null) { 
    postResponseOutput += tempString; 
} 
Log.d("HttpResponse Output", postResponseOutput); 

對於準系統形式,我做了要求在AT /了testForm網址登錄的錯誤,因此谷歌的登錄頁面被退回,而不是我的方式。消除該限制使表單完美工作。

嘗試使用我的代碼的MultipartEntityBuilder部分,在帖子響應中返回了一些有趣的內容,無非是「請求的內容類型不被此URL接受」。但嘗試與MultipartEntity部分似乎是伎倆。 httpresponse返回了內部服務器錯誤(與用戶身份驗證有關)。這就解釋了爲什麼發佈到原始webform不起作用 - 有一個服務器錯誤首先阻止了表單被訪問。我相信,一旦我解決了這個錯誤,那麼表單就會像我的testForm一樣工作。

+0

作爲附註:您的multipartEntity和您的multipartEntityBuilder之間的區別是StringBody的內容類型:在第一種情況下,您指定「ContentType.MULTIPART_FORM_DATA」,在第二種情況下,您不需要,默認值爲「」文本/平原「' – njzk2 2014-10-27 22:15:13

+0

好的,這是有道理的。使用其中一種的好處是什麼? – Pete 2014-10-27 22:17:31

+0

建設者vs非建設者?不是真的。生成器遵循生成器模式,它允許您鏈接調用。這實際上只是你喜歡用什麼。幕後,建設者實際上只是在調用相同的方法。 – njzk2 2014-10-27 22:36:09