2015-11-02 62 views
5

我正在使用Square Retrofit 2.0版beta2。我試圖按照this tutorial .我試圖上傳一個位圖圖像到服務器,但不知何故代碼無法正常工作。我試圖用郵遞員測試我的服務器,我能夠張貼照片,甚至能夠檢索它。這是我的燒瓶控制器。翻新(2.0 beta2)多部分文件上傳不起作用

@app.route('/api/photo/user/<int:user_id>', methods=["POST"]) 
    def post_user_photo(user_id): 
     app.logger.info("post_user_photo=> user_id:{}, photo: {}".format(
      user_id, 
      request.files['photo'].filename, 
     )) 
     user = User.query.get_or_404(user_id) 
     try: 
      user.photo = request.files['photo'].read() 
     except Exception as e: 
      app.logger.exception(e) 
      db.session.rollback() 
      raise 
     db.session.commit() 
     return "", codes.no_content 

我已經使用郵遞員來測試我的控制器,這裏是郵遞員產生的請求。

POST /api/photo/user/5 HTTP/1.1 
Host: blooming-cliffs-9672.herokuapp.com 
Cache-Control: no-cache 
Postman-Token: 8117fb79-4781-449d-7d22-237c49b53389 
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW 

----WebKitFormBoundary7MA4YWxkTrZu0gW 
Content-Disposition: form-data; name="photo"; filename="sfsu.jpg" 
Content-Type: image/jpeg 


----WebKitFormBoundary7MA4YWxkTrZu0gW 

我已經定義了翻新服務和上傳圖片,這裏是我的Android代碼。接口部分

@Multipart 
    @POST("/api/photo/user/{userId}") 
    Call<Void> uploadUserProfilePhoto(@Path("userId") Integer userId, @Part("photo") RequestBody photo); 

這裏客戶端部分建設者

public static BeamItService getService(){ 
     if (service == null) { 
      OkHttpClient client = new OkHttpClient(); 
      HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(); 
      interceptor.setLevel(HttpLoggingInterceptor.Level.BODY); 
      HttpLoggingInterceptor interceptor2 = new HttpLoggingInterceptor(); 
      interceptor.setLevel(HttpLoggingInterceptor.Level.HEADERS); 

      client.interceptors().add(interceptor); 
      client.interceptors().add(interceptor2); 

      service = new Retrofit.Builder() 
        .baseUrl(BASE_URL) 
        .client(client) 
        .addConverterFactory(GsonConverterFactory.create()) 
        .build().create(BeamItService.class); 
     } 
     return service; 
    } 

這裏是它試圖上傳位圖Android的活動代碼。

private void uploadProfilePhoto(){ 
     BeamItService service = BeamItServiceTransport.getService(); 

     MediaType MEDIA_TYPE_PNG = MediaType.parse("image/jpeg"); 
     byte [] data = BitmapUtility.getBitmapToBytes(((BitmapDrawable) ivProfilePhoto.getDrawable()).getBitmap()); 
     Log.d(TAG, String.format("Profile detals => user_id: %d, size of data: %d", 5, data.length)); 

     RequestBody requestBody1 = RequestBody.create(MEDIA_TYPE_PNG, 
                data); 
     Log.d(TAG, "requestBody: " + requestBody1.toString()); 
     RequestBody requestBody2 = new MultipartBuilder() 
       .type(MultipartBuilder.FORM) 
       .addPart(Headers.of("Content-Disposition", "form-data; name=\"photo\"; filename=\"t.jpg\""), 
         requestBody1) 
       .build(); 
     Log.d(TAG, "requestBody: " + requestBody2.toString()); 
//  ProfileDetails profileDetails = new DBHelper(this).fetchProfileDetails(); 

     Call<Void> call = service.uploadUserProfilePhoto(5, requestBody2); 
     call.enqueue(new ProfilePhotoUploadCallback()); 
    } 

    private class ProfilePhotoUploadCallback implements Callback<Void> { 

     @Override 
     public void onResponse(Response<Void> response, Retrofit retrofit) { 
      Log.d(TAG, String.format("ProfilePhotoUploadCallback=> code: %d", response.code())); 
     } 

     @Override 
     public void onFailure(Throwable t) { 

     } 
    } 

但它無法上傳它,燒瓶應用程序每次返回狀態代碼400。我試圖把斷點放在燒瓶應用程序中,但請求甚至沒有到達那裏。 這裏是服務器日誌

2015-11-02T06:05:42.288574+00:00 heroku[router]: at=info method=POST path="/api/photo/user/5" host=blooming-cliffs-9672.herokuapp.com request_id=2cc8b6c8-f12a-4e4b-8279-cedfc39712f2 fwd="204.28.113.240" dyno=web.1 connect=1ms service=88ms status=400 bytes=347 
2015-11-02T06:05:42.209347+00:00 app[web.1]: [2015-11-02 06:05:42 +0000] [11] [DEBUG] POST /api/photo/user/5 

我也試圖使改造截擊和日誌的請求和響應,但我沒有得到整個POST請求主體。這是Android日誌。

11-02 00:24:22.119 3904-4382/com.contactsharing.beamit D/OkHttp: --> POST /api/photo/user/5 HTTP/1.1 
11-02 00:24:22.119 3904-4382/com.contactsharing.beamit D/OkHttp: Content-Type: multipart/form-data; boundary=4031e177-0e4b-4f16-abe8-20c54e506846 
11-02 00:24:22.120 3904-4382/com.contactsharing.beamit D/OkHttp: Content-Length: 17171 
11-02 00:24:22.120 3904-4382/com.contactsharing.beamit D/OkHttp: Host: blooming-cliffs-9672.herokuapp.com 
11-02 00:24:22.120 3904-4382/com.contactsharing.beamit D/OkHttp: Connection: Keep-Alive 
11-02 00:24:22.120 3904-4382/com.contactsharing.beamit D/OkHttp: Accept-Encoding: gzip 
11-02 00:24:22.120 3904-4382/com.contactsharing.beamit D/OkHttp: User-Agent: okhttp/2.6.0-SNAPSHOT 
11-02 00:24:22.120 3904-4382/com.contactsharing.beamit D/OkHttp: --> END POST 
11-02 00:24:22.179 3904-4537/com.contactsharing.beamit I/DBHelper: Updated row: 1 
11-02 00:24:22.316 3904-4382/com.contactsharing.beamit D/OkHttp: <-- HTTP/1.1 400 BAD REQUEST (195ms) 
11-02 00:24:22.316 3904-4382/com.contactsharing.beamit D/OkHttp: Connection: keep-alive 
11-02 00:24:22.316 3904-4382/com.contactsharing.beamit D/OkHttp: Server: gunicorn/19.3.0 
11-02 00:24:22.316 3904-4382/com.contactsharing.beamit D/OkHttp: Date: Mon, 02 Nov 2015 08:24:22 GMT 
11-02 00:24:22.316 3904-4382/com.contactsharing.beamit D/OkHttp: Content-Type: text/html 
11-02 00:24:22.316 3904-4382/com.contactsharing.beamit D/OkHttp: Content-Length: 192 
11-02 00:24:22.316 3904-4382/com.contactsharing.beamit D/OkHttp: Via: 1.1 vegur 
11-02 00:24:22.316 3904-4382/com.contactsharing.beamit D/OkHttp: OkHttp-Selected-Protocol: http/1.1 
11-02 00:24:22.316 3904-4382/com.contactsharing.beamit D/OkHttp: OkHttp-Sent-Millis: 1446452662120 
11-02 00:24:22.316 3904-4382/com.contactsharing.beamit D/OkHttp: OkHttp-Received-Millis: 1446452662316 
11-02 00:24:22.316 3904-4382/com.contactsharing.beamit D/OkHttp: <-- END HTTP 

請幫助,我卡住了,無法取得任何進展。

回答

11

您正在此處嵌套多部分請求主體(多部分內的多部分)。

最近執行了類似的操作,而不是使用@Multipart@Part,您可以使用@BodyMultipartBuilder

@POST("/api/photo/user/{userId}") 
Call<Void> uploadUserProfilePhoto(@Path("userId") Integer userId, @Body RequestBody photo); 

然後,而不是使用MultipartBuilder.addPart(...)使用MultipartBuilder.addFormDataPart(name, filename, requestBody)

private void uploadProfilePhoto() { 
    BeamItService service = BeamItServiceTransport.getService(); 

    MediaType MEDIA_TYPE_PNG = MediaType.parse("image/jpeg"); 
    byte [] data = BitmapUtility.getBitmapToBytes(((BitmapDrawable) ivProfilePhoto.getDrawable()).getBitmap()); 
    Log.d(TAG, String.format("Profile detals => user_id: %d, size of data: %d", 5, data.length)); 

    RequestBody requestBody1 = RequestBody.create(MEDIA_TYPE_PNG, data); 
    Log.d(TAG, "requestBody: " + requestBody1.toString()); 
    RequestBody requestBody2 = new MultipartBuilder() 
      .type(MultipartBuilder.FORM) 
      .addFormDataPart("photo", "t.jpg", requestBody1) 
      .build(); 
    Log.d(TAG, "requestBody: " + requestBody2.toString()); 
// ProfileDetails profileDetails = new DBHelper(this).fetchProfileDetails(); 

    Call<Void> call = service.uploadUserProfilePhoto(5, requestBody2); 
    call.enqueue(new ProfilePhotoUploadCallback()); 
} 
+0

它的工作魅力感謝一樣不少。你拯救了我的一天。 –

+0

是的,它也適用於我。非常感謝! – Kaizie

+0

非常感謝。你救了我的一天:) –