Upload image via volley throwing error. Having array of image and array of text [duplicate]
Asked Answered
K

1

4

Solution Given below

I am using volley library to upload image. Condition is I require to send

  1. key1 = String value
  2. key2 = String value
  3. key3{=file} = Image value i.e. jpeg, jpg

This is the code I am using (commented portion is something I have already tried) -

import com.android.volley.AuthFailureError;
import com.android.volley.NetworkResponse;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.VolleyLog;
import com.android.volley.toolbox.HttpHeaderParser;
import <APP_CLASS IGNORE THIS>.Config

import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.util.CharsetUtils;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * Created by Jimit Patel on 26/09/15.
 */
public class MyClass extends Request<String> {

    private static final String TAG = MyClass.class.getSimpleName();
    private static final boolean IS_DEBUG = true;
    private static final String FILE_PART_NAME = "file";

    private MultipartEntityBuilder multipartEntityBuilder;
    private Response.Listener<String> mListener;
    private Map<String, String> mRequestParams;
    private File file;
    private String tokenId;

    public AddWardrobeRequest(int method, String url, Response.Listener<String> listener, Response.ErrorListener errorListener,
                              File file, Map<String, String> requestParams, String tokenId) {
        super(method, url, errorListener);

        mListener = listener;
        this.file = file;
        this.tokenId = tokenId;
        mRequestParams = requestParams;

        buildMultipartEntity();
    }

    @Override
    protected Response<String> parseNetworkResponse(NetworkResponse response) {
        return Response.success("Result", getCacheEntry());
    }

    @Override
    protected void deliverResponse(String response) {
        mListener.onResponse(response);
    }

    @Override
    public Map<String, String> getHeaders() throws AuthFailureError {
        Map<String, String> headers = super.getHeaders();

        if (headers == null
                || headers.equals(Collections.emptyMap())) {
            headers = new HashMap<>();
        }
        headers.put(Config.HEADER_AUTHORIZATION, "Bearer " + tokenId);
//        headers.put("Accept", "application/json");
//        headers.put("Content-Type", "multipart/form-data");

        return headers;
    }

    @Override
    public String getBodyContentType() {
        String contentTypeHeader = multipartEntityBuilder.build().getContentType().getValue();
        return contentTypeHeader;
    }

    @Override
    public byte[] getBody() throws AuthFailureError {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        try {
            multipartEntityBuilder.build().writeTo(bos);
        } catch (IOException e) {
            VolleyLog.e("IOException writing to ByteArrayOutputStream bos, building the multipart request.");
        }

        return bos.toByteArray();
    }

    private void buildMultipartEntity() {
        multipartEntityBuilder = MultipartEntityBuilder.create();
        multipartEntityBuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
//        multipartEntityBuilder.setLaxMode().setBoundary("xx").setCharset(Charset.forName("UTF-8"));
//        try {
//            multipartEntityBuilder.setCharset(CharsetUtils.get("UTF-8"));
//        } catch (UnsupportedEncodingException e) {
//            e.printStackTrace();
//        }
        multipartEntityBuilder.addPart(FILE_PART_NAME, new FileBody(file) );
        Set<String> keys = mRequestParams.keySet();
        for (String key : keys)
            multipartEntityBuilder.addTextBody(key, mRequestParams.get(key));
    }
}

Below is the error which I am facing.

Process: com.stylabs.APP.app, PID: 12804
java.lang.NoSuchFieldError: No static field INSTANCE of type Lorg/apache/http/message/BasicHeaderValueFormatter; in class Lorg/apache/http/message/BasicHeaderValueFormatter; or its superclasses (declaration of 'org.apache.http.message.BasicHeaderValueFormatter' appears in /system/framework/ext.jar)
        at org.apache.http.entity.ContentType.toString(ContentType.java:153)
        at org.apache.http.entity.mime.MultipartFormEntity.<init>(MultipartFormEntity.java:53)
        at org.apache.http.entity.mime.MultipartEntityBuilder.buildEntity(MultipartEntityBuilder.java:236)
        at org.apache.http.entity.mime.MultipartEntityBuilder.build(MultipartEntityBuilder.java:240)
        at MyClass.getBody(MyClass.java:90)
        at com.android.volley.toolbox.HurlStack.addBodyIfExists(HurlStack.java:253)
        at com.android.volley.toolbox.HurlStack.setConnectionParametersForRequest(HurlStack.java:227)
        at com.android.volley.toolbox.HurlStack.performRequest(HurlStack.java:107)
        at com.android.volley.toolbox.BasicNetwork.performRequest(BasicNetwork.java:96)
        at com.android.volley.NetworkDispatcher.run(NetworkDispatcher.java:112)

Please help me out. Thank you in advance!!

SOLUTION

Although as marked as duplicate I didn't found any solution over there. I finally cracked out what I was missing. I re-read the document over android which I can find it over here - http://developer.android.com/preview/behavior-changes.html#behavior-apache-http-client

So I have removed all those httpcomponents which includes httpcore, httpmime, httpclient, etc. Don't know now which all crap stuffs were suggested all over stack overflow, all were right maybe till yesterday but not with M preview+. Instead of that add

android {
   useLibrary 'org.apache.http.legacy'
}

And the request class which has been used earlier is changed as given below -

import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    
    import com.android.volley.AuthFailureError;
    import com.android.volley.NetworkResponse;
    import com.android.volley.Request;
    import com.android.volley.Response;
    import com.android.volley.VolleyError;
    import <APP_CLASS IGNORE THIS>.Config
    
    import java.io.ByteArrayInputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.DataOutputStream;
    import java.io.File;
    import java.io.IOException;
    import java.util.Collections;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.Set;
    
    /**
     * Created by Jimit Patel on 26/09/15.
     */
    public class MyClass extends Request<String> {
    
        private static final String TAG = AddWardrobeRequest.class.getSimpleName();
        private static final boolean IS_DEBUG = true;

// This is the key for the file to be sent
        private static final String FILE_PART_NAME = "file";
    
        private Response.Listener<String> mListener;
        private Response.ErrorListener mErrorListener;
        private Map<String, String> mRequestParams;
        private File file;
        private String tokenId;
    
        private final String BOUNDARY = "3i2ndDfv2rTHiSisAbouNdArYfORhtTPEefj3q2f";
        private final String CRLF = "\r\n";
        private final int MAX_BUFFER_SIZE = 1024 * 1024;
    
        public MyClass(int method, String url, Response.Listener<String> listener, Response.ErrorListener errorListener,
                                  File file, Map<String, String> requestParams, String tokenId) {
            super(method, url, errorListener);
    
            mListener = listener;
            mErrorListener = errorListener;
            this.file = file;
            this.tokenId = tokenId;
            mRequestParams = requestParams
        }
    
        @Override
        protected Response<String> parseNetworkResponse(NetworkResponse response) {
            return Response.success(new String(response.data), getCacheEntry());
        }
    
        @Override
        protected void deliverResponse(String response) {
            mListener.onResponse(response);
        }
    
        @Override
        public Map<String, String> getHeaders() throws AuthFailureError {
            Map<String, String> headers = super.getHeaders();
    
            if (headers == null
                    || headers.equals(Collections.emptyMap())) {
                headers = new HashMap<>();
            }
            headers.put(Config.HEADER_AUTHORIZATION, "Bearer " + tokenId);
            headers.put("Content-Type", "multipart/form-data; boundary=" + BOUNDARY);
    
            return headers;
        }
    
        @Override
        protected VolleyError parseNetworkError(VolleyError volleyError) {
            return super.parseNetworkError(volleyError);
        }
    
        @Override
        public void deliverError(VolleyError error) {
            mErrorListener.onErrorResponse(error);
        }
    
        @Override
        public byte[] getBody() throws AuthFailureError {
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
    DataOutputStream dos = new DataOutputStream(bos);
    try {
        PrintWriter pw = new PrintWriter(new OutputStreamWriter(dos, "UTF-8"));

        Set<String> keys = mRequestParams.keySet();


pw.append(CRLF);
        for (String key : keys) {
            pw.append("--" + BOUNDARY + CRLF);
            pw.append("Content-Disposition: form-data; ");
            pw.append("name=\"" + key + "\"" + CRLF + CRLF + mRequestParams.get(key) + CRLF);
        }

        pw.append("--" + BOUNDARY + CRLF);
        pw.append("Content-Disposition: form-data; ");
        pw.append("name=\"" + FILE_PART_NAME + "\"; filename=\"" + file.getName() + "\"" + CRLF + CRLF);

        dos.writeBytes(pw.toString());
        pw.flush();
        FileInputStream inputStream = new FileInputStream(file);
        int bytesAvailable = inputStream.available();
        int bufferSize = Math.min(bytesAvailable, MAX_BUFFER_SIZE);
        byte[] buffer = new byte[bufferSize];
        int bytesRead;
        while ((bytesRead = inputStream.read(buffer)) != -1)
            dos.write(buffer, 0, bytesRead);

        dos.writeBytes(CRLF + "--" + BOUNDARY + "--" + CRLF);
    } catch (IOException e) {
        e.printStackTrace();
    }
    return bos.toByteArray();
        }
    }

And finally got the proper response as desired. I hope this will help others out who all are in trouble same as me. :)

Kisser answered 26/9, 2015 at 11:37 Comment(0)
D
1

https://github.com/alexbbb/android-upload-service

Look into this library. You can customize the service also. This is a well written file upload service for android.

Disaffection answered 26/9, 2015 at 11:41 Comment(1)
sorry buddy, I have found out the solution, didn't want to add more libraries... Thanks anywaysKisser

© 2022 - 2024 — McMap. All rights reserved.