简体   繁体   English

将json post请求更改为multipart / form-data

[英]Change a json post request to multipart/form-data

I was trying to develop a simple POST API call in Android so I made one thinking that the request content-type was a json. 我试图在Android中开发一个简单的POST API调用,所以我认为请求内容类型是一个json。 Turns out it is expecting a multipart/form-data format and I'm struggling changing my function. 原来它期待一个multipart/form-data格式,我正在努力改变我的功能。 I'd like to know if there is any library to manage this. 我想知道是否有任何图书馆来管理这个。 If not, I'd like to know how to pass my arguments in a multipart format. 如果没有,我想知道如何以多部分格式传递我的参数。

@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;
    }

I hardcoded some of the values because I wanted to test with poiID and description 我硬编码了一些值,因为我想用poiIDdescription进行测试

So I want to send these kind of values in my multipart/form-date: - poiID : String - description : String - resource : image - tags 所以我想在我的multipart / form-date中发送这些值: - poiID:String - description:String - resource:image - tags

Is there any way to do this similar to the way I made my json request? 有没有办法像我提出json请求那样做?

Kind regards 亲切的问候

EDIT: 编辑:

@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;
}

How do I add the headers? 如何添加标题?

If it isn't JSON, simply use a StringRequest. 如果它不是JSON,只需使用StringRequest。

Not sure how to use Future with Volley, so change that accordingly 不确定如何使用Future with Volley,所以相应地改变它

Then, params are added in an overridden method 然后,以重写方法添加参数

    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
        }
    };

And for Multipart, see Working POST Multipart Request with Volley and without HttpEntity 对于Multipart,请参阅使用Volley和没有HttpEntity工作POST多部分请求

Using Retrofit 2, you could do this: 使用Retrofit 2,您可以这样做:

//Lets Suppose this you have this postman or you want to make some request like this //让我们假设你有这个邮递员,或者你想提出这样的要求 邮差要求

//ServiceCreator (In my case i am using oauth2 so have AccessToken). // ServiceCreator(在我的情况下,我使用oauth2,所以有AccessToken)。 This is a working and production sample, so you have to make your own changes, but i attach to example all components. 这是一个工作和生产示例,因此您必须进行自己的更改,但我附加示例所有组件。

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 // 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 (in your activity, fragment or wetheaver) this should be used when you execute your api call // 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
    }
});

I have used this to upload photos, so i have to use this sample to do that, thats the reason i did not use Content Type application/json. 我用它来上传照片,所以我必须使用这个样本来做到这一点,这就是我没有使用Content Type application / json的原因。

Hope that helps how to do. 希望有助于该怎么做。

Some class (pojo) like TareaCalificacion (that is what i expect from the response are just class, that i use with GSON), so TareaCalificacion.java is like: 像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() {
    }
}

Attach some links that could help you if you have doubts: 如果您有疑问,请附上一些可以帮助您的链接:

Retrofit Documentation 改造文件

Another example using this 使用此的另一个例子

Lets me know if that works or if is not clear how to do Regards. 让我知道如果有效或如果不清楚如何做问候。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM