2017-05-31 103 views
1

我试图开发Android的一个简单的POST的API调用,所以我提出一个想法,该请求内容类型是JSON。原来它是期待一个multipart/form-data格式和我挣扎改变我的功能。 我想知道是否有任何库来管理这一点。如果不是,我想知道如何以多部分格式传递我的论点。更改JSON post请求为multipart/form-数据

@Override 
    public boolean post(String poiId, String description, ArrayList<String> tags, Resource resource) { 

     RequestQueue queue = mRequestQueue; 
     poiId = "1"; 
     description = "Test post"; 
     final HashMap<String, Object> params = new HashMap<>(); 
     params.put("poiID", poiId); 
     params.put("description", description); 
     System.out.println("POI ID " + description); 
     params.put("tags", tags); 
     params.put("resource", resource); 


     RequestFuture<JSONObject> future = RequestFuture.newFuture(); 
     JsonObjectRequest request = new JsonObjectRequest(
       Request.Method.POST, 
       API_POST_URL, 
       new JSONObject(params), 
       future, future) { 
      @Override 
      public HashMap<String, String> getHeaders() { 
       System.out.println(PostRepositoryImpl.this.getHeaders()); 
       return PostRepositoryImpl.this.getHeaders(); 
      } 
     }; 

     queue.add(request); 

     try { 
      future.get(TIMEOUT, TIMEOUT_TIME_UNIT); // this will block 
     }catch (InterruptedException | ExecutionException | TimeoutException e){ 
      e.printStackTrace(); 
      return false; 
     } 
     return true; 
    } 

我硬编码一些值,因为我想与poiIDdescription

所以我想在我的multipart /表单日期发送这些类型的值来测试: - poiID:字符串 - 描述:字符串 - 资源:图像 - 标签

有没有办法做到这一点类似于我在我的JSON请求的方式吗?

亲切的问候

编辑:

@Override 
public boolean post(String poiId, String description, ArrayList<String> tags, Resource resource) { 
    RequestQueue queue = mRequestQueue; 
    StringRequest postRequest = new StringRequest(Request.Method.POST, API_POST_URL, 
      new Response.Listener<String>() 
      { 
       @Override 
       public void onResponse(String response) { 
        // response 
        Log.d("Response", response); 
       } 
      }, 
      new Response.ErrorListener() 
      { 
       @Override 
       public void onErrorResponse(VolleyError error) { 
        // error 
        Log.d("Error.Response", "400"); 
       } 
      } 
    ) { 
     @Override 
     protected HashMap<String, String> getParams() 
     { 
      HashMap<String, String> params = new HashMap<String, String>(); 
      params.put("poiID", "Alif"); 
      params.put("description", "http://itsalif.info"); 

      return params; 
     } 
    }; 
    queue.add(postRequest); 

    return true; 
} 

如何添加标题?

+0

您是否使用Volley ?,我建议您使用Retrofit 2,它更好,更好,让我知道如果您想要一个关于如何使用Retrofit发送多部分数据的示例。 Regards –

+0

不幸的是,我正在使用Volley。但非常感谢:) –

+0

花点时间来检查这个要点https://gist.github.com/alphamu/684d8ae311d95831ce1c –

回答

0

如果不是JSON,简单地用一个StringRequest。

不知道如何使用未来排球,所以更改相应

然后,则params在被覆盖的方法添加

Request request = new StringRequest(
      Request.Method.POST, 
      API_POST_URL, 
      future, future) { 
     @Override 
     public HashMap<String, String> getHeaders() { 
      HashMap<String, String> headers = PostRepositoryImpl.this.getHeaders(); 
      System.out.println(headers); 
      return headers; 
     } 
     @Override 
     public HashMap<String, String> getParams() { 
      // TODO: Put your params here 
     } 
    }; 

而对于多部分,见Working POST Multipart Request with Volley and without HttpEntity

+0

看看我的编辑请@ cricket_007。如何将标题添加到我的请求中? –

+0

你已经在添加标题了...我不明白这个问题 –

+0

标题添加得很差,看起来我不能在那里。另外,我再次编辑,并遵循你的实现,它给了我硬编码400. @ cricket_007 –

0

使用改造2 ,你可以这样做:

//让我们假设这个你有这样的邮递员或你想这样有一定的要求postman request

// ServiceCreator(在我的情况下,我使用oauth2,所以有AccessToken)。这是一个工作和生产样本,所以你必须做出自己的改变,但我附加示例所有组件。

public class APIRestClient { 

    public static String API_BASE_URL = "http://186.151.238.14/"; 

    private static OkHttpClient.Builder httpClient; 

    private static Retrofit.Builder builder; 
    public static Retrofit retrofit; 
    private static Activity mActivity; 
    private static AccessToken mToken; 

    /** 
    * setupBase URL 
    * @param _baseActivity 
    */ 
    public static void setupBaseUrl(Context _baseActivity){ 
     String tmpBase = SharedPreferenceUtilities.getDomain(_baseActivity); 
     if (tmpBase != null && tmpBase.length() > 0){ 
      if (tmpBase != API_BASE_URL) { 
       APIRestClient.API_BASE_URL = tmpBase; 
      } 
     } 
    } 

    /** 
    * auth2 Authorization Bearer...token create Service instance 
    * @param _serviceClass 
    * @param _baseActivity 
    * @param <S> 
    * @return 
    */ 
    public static <S> S createService(Class<S> _serviceClass, final Activity _baseActivity) { 
     AccessToken accessToken = TaskManagementApplication.getInstance().getAccessToken(); 
     if (_baseActivity != null) { 
      setupBaseUrl(_baseActivity); 
     } 

     httpClient = new OkHttpClient.Builder(); 
     httpClient.connectTimeout(30000, TimeUnit.SECONDS) 
       .readTimeout(30000,TimeUnit.SECONDS); 

     if (BuildConfig.DEBUG) { 
      HttpLoggingInterceptor logging = new HttpLoggingInterceptor(); 
      logging.setLevel(HttpLoggingInterceptor.Level.BODY); 
      httpClient.addInterceptor(logging); 
      httpClient.addNetworkInterceptor(new StethoInterceptor()); 
     } 

     builder = new Retrofit.Builder() 
       .baseUrl(API_BASE_URL) 
       .addConverterFactory(GsonConverterFactory.create()); 

     if (accessToken == null){ 
      accessToken = new AccessToken(); 
      accessToken.setAccessToken(""); 
      accessToken.setTokenType("Bearer"); 
      accessToken.setScope(""); 
      accessToken.setRefreshToken(""); 
      accessToken.setClientID(""); 
      accessToken.setClientSecret(""); 
      accessToken.setExpiry(0); 
     } 

     if(accessToken != null) { 
      mActivity = _baseActivity; 
      mToken = accessToken; 
      final AccessToken token = accessToken; 
      httpClient.addInterceptor(new Interceptor() { 
       @Override 
       public Response intercept(Chain chain) throws IOException { 
        Request original = chain.request(); 

        Request.Builder requestBuilder = original.newBuilder() 
          .header("Accept", "application/json") 
          .header("Content-type", "application/json") 
          .header("Authorization", 
            token.getTokenType() + " " + token.getAccessToken()) 
          .method(original.method(), original.body()); 

        Request request = requestBuilder.build(); 
        return chain.proceed(request); 
       } 
      }); 

      httpClient.authenticator(new Authenticator() { 
       @Override 
       public Request authenticate(Route route, Response response) throws IOException { 
        if(responseCount(response) >= 2) { 
         // If both the original call and the call with refreshed token failed, 
         // it will probably keep failing, so don't try again. 
         LoginUtilities.initLogin(_baseActivity,LoginActivity.LOGININTENTRESULT,null); 
         return null; 
        } 

        // We need a new client, since we don't want to make another call using our client with access token 
        OAuthInterface tokenClient = createAuthService(OAuthInterface.class,mActivity); 
        Call<AccessToken> call = tokenClient.getRefreshAccessToken(
          Grant_type.REFRESH_TOKEN.toString(), 
          token.getRefreshToken(), 
          StringUtilities.API_OAUTH_CLIENTID(_baseActivity), 
          StringUtilities.API_OAUTH_SECRET(_baseActivity), 
          ""); 
        try { 
         retrofit2.Response<AccessToken> tokenResponse = call.execute(); 
         if(tokenResponse.code() == 200) { 
          AccessToken newToken = tokenResponse.body(); 
          mToken = newToken; 
          SharedPreferenceUtilities.setAccessToken(mActivity,mToken); 
          TaskManagementApplication.getInstance().setupToken(mToken); 

          return response.request().newBuilder() 
            .header("Authorization", newToken.getTokenType() + " " + newToken.getAccessToken()) 
            .build(); 
         } else { 
          LoginUtilities.initLogin(_baseActivity,LoginActivity.LOGININTENTRESULT,null); 
          return null; 
         } 
        } catch(IOException e) { 
         LoginUtilities.initLogin(_baseActivity,LoginActivity.LOGININTENTRESULT,null); 
         return null; 
        } 
       } 
      }); 
     } 

     OkHttpClient client = httpClient.build(); 
     Retrofit retrofit = builder.client(client).build(); 
     return retrofit.create(_serviceClass); 
    } 

    /** 
    * not auth create Service instance 
    * @param _serviceClass 
    * @param _context 
    * @param <S> 
    * @return 
    */ 

    private static int responseCount(Response response) { 
     int result = 1; 
     while ((response = response.priorResponse()) != null) { 
      result++; 
     } 
     return result; 
    } 
} 

// ApiInterface

public interface StudentInterface 
    { 
     public static final String ENVIARTAREAAPI = "api/estudiante/entregatarea"; 
     @Multipart 
     @POST(ENVIARTAREAAPI) 
     Call<TareaCalificacion> entregatarea(@Part("Descripcion") RequestBody Descripcion, 
              @Part("IdTarea") RequestBody IdTarea, 
              @Part("IdEstudiante") RequestBody IdEstudiante); 

    } 

// ApiCall(在你的活动,片段或wetheaver),当您执行API调用本应使用

RequestBody descripcionRequestBody = RequestBody.create(
       okhttp3.MediaType.parse("text/plain; charset=utf-8"), 
       mensageEntregaTmp); 

RequestBody idTareaRequestBody = RequestBody.create(
       okhttp3.MediaType.parse("text/plain; charset=utf-8"), 
       String.valueOf(mTarea.getIdTarea())); 

RequestBody idEstudianteRequestBody = RequestBody.create(
       okhttp3.MediaType.parse("text/plain; charset=utf-8"), 
       String.valueOf(currUser.getPerfil().getSisId())); 

StudentInterface studentInterface = APIRestClient.createService(StudentInterface.class,DetalleTareaActivity.this); 
Call<TareaCalificacion> call = studentInterface.entregatarea(
     descripcionRequestBody, 
     idTareaRequestBody, 
     idEstudianteRequestBody); 

call.enqueue(new Callback<TareaCalificacion>() { 
    @Override 
    public void onResponse(Call<TareaCalificacion> call, Response<TareaCalificacion> response) { 
     int statusCode = response.code(); 
     if(statusCode == 200) { 
      Toast.makeText(getApplicationContext, "Success Request", Toast.LENGTH_SHORT).show(); 
     } else { 
      //todo some kind of error 
     } 
    } 
    @Override 
    public void onFailure(Call<TareaCalificacion> call, Throwable t) { 
     //todo some kind of error 
    } 
}); 

我已经使用这个上传照片,所以我不得不使用这个样本来做到这一点,这就是我没有使用Content Type application/json的原因。

希望帮助该怎么办。

像TareaCalificacion这样的类(pojo)(这是我期望的响应只是类,我使用GSON),所以TareaCalificacion。Java是这样的:

public class TareaCalificacion { 
    @SerializedName("sisId") 
    @Expose 
    private long sisId; 

    @SerializedName("sisDescripcion") 
    @Expose 
    private String sisDescripcion; 

    @SerializedName("sisEstado") 
    @Expose 
    private String sisEstado; 

    @SerializedName("sis") 
    @Expose 
    private int sis; 

    @SerializedName("sisUsuario") 
    @Expose 
    private String sisUsuario; 

    @SerializedName("CalificacionObtenida") 
    @Expose 
    private double CalificacionObtenida; 

    @SerializedName("IdEstudiante") 
    @Expose 
    private long IdEstudiante; 

    @SerializedName("IdTarea") 
    @Expose 
    private long IdTarea; 

    @SerializedName("Adjunto") 
    @Expose 
    private int Adjunto; 

    @SerializedName("ObservacionCalificacion") 
    @Expose 
    private String ObservacionCalificacion; 

    @SerializedName("IdCatedratico") 
    @Expose 
    private long IdCatedratico; 

    public TareaCalificacion() { 
    } 
} 

附上一些链接,可以帮助你,如果你有疑问:

Retrofit Documentation

Another example using this

让我知道是否可行,或者并不清楚如何 问候。