1

After many tries I Solved it, there is the code i use to send parameters and image :

    public class PurchaseAsync extends AsyncTask<String, Void, Boolean> {

    public static final String TAG = PurchaseAsync.class.getSimpleName();
    public PurchaseAsync(ArrayList<CustomItem> parameters, String imageAddress, PurchaseListener listener){
        this.parameters = parameters;
        this.imageAddress = imageAddress;
        this.listener = listener;
        if(this.parameters == null){
            this.parameters = new ArrayList<>();
        }
        LTH.dLog(WMH.WEBSERVICE, TAG + " -> Image path : " + imageAddress);
    }
    private String imageAddress = "";
    // ========== Use HashMap, it works similar to NameValuePair
    ArrayList<CustomItem> parameters = new ArrayList<>();
    private PurchaseListener listener;
    public interface PurchaseListener {
        void execute(int exception, Boolean success, FactorItem msg);
    }
    private int customException = WMH.NO_EXCEPTION;
    private FactorItem msg = new FactorItem();
    @Override
    protected void onPreExecute() {
        progressDialog = ProgressDialog.show(App.getActivity(),
                "", App.getContext().getString(R.string.pb_msg_purchase_request), true, false);
        progressDialog.setCanceledOnTouchOutside(false);
        super.onPreExecute();
    }
    private ProgressDialog progressDialog;
    @Override
    protected void onPostExecute(Boolean success) {
        super.onPostExecute(success);
        if(progressDialog != null){
            progressDialog.dismiss();
        }
        LTH.dLog(WMH.WEBSERVICE, TAG + " -> customException : " + customException + " , Success : " + success);
        if(listener != null){
            listener.execute(customException, success, msg);
        }
    }

    @Override
    protected Boolean doInBackground(String... strings) {
        customException = WMH.NO_EXCEPTION;
        try{
            String strResult = readData(strings[0]);
            if(strResult.equals("")){
                customException = customException == WMH.NO_EXCEPTION ? WMH.INVALID_EXCEPTION : customException;
                return false;
            }else{
                JSONObject jsonObject = jsonParser(strResult);
                if(jsonObject == null){
                    customException = customException == WMH.NO_EXCEPTION ? WMH.INVALID_EXCEPTION : customException;
                    return false;
                }
                pareFactor(jsonObject);
                if (jsonObject.has("status")) {
                    return jsonObject.getBoolean("status");
                } else {
                    customException = customException == WMH.NO_EXCEPTION ? WMH.INVALID_EXCEPTION : customException;
                    return false;
                } // end of else/if
            }
        }catch (Exception e){
            customException = customException == WMH.NO_EXCEPTION ? WMH.INVALID_EXCEPTION : customException;
            LTH.eLog(WMH.JSON, TAG + " -> Exception Error In Json: " + e.getMessage(), e);
        }
        return false;
    }
    private void pareFactor(JSONObject iJsonObject) throws Exception{
        if (iJsonObject.has("result")) {
            if(iJsonObject.get("result") == null){
                return;
            }
            if(!(iJsonObject.get("result") instanceof JSONObject)){
                return;
            }
            JSONObject jsonObject = iJsonObject.getJSONObject("result");
            if(jsonObject.has("code")){
                String code = jsonObject.getString("code");
                msg.setCode(code);
                int fid;
                try {
                    fid = Integer.parseInt(jsonObject.getString("fid"));
                }catch (NumberFormatException nfe){
                    fid = 0;
                    // throw new Exception("Factor ID Not Assigned Correctly");
                }
                msg.setItemId(fid);
                if(jsonObject.has("price_number")) {
                    String price_number = jsonObject.getString("price_number");
                    msg.setPayment(price_number);
                    msg.setTotal(price_number);
                }
                if(jsonObject.has("price")) {
                    int price;
                    try {
                        price = Integer.parseInt(jsonObject.getString("price"));
                    }catch (NumberFormatException nfe){
                        price = 0;
                        // throw new Exception("Factor ID Not Assigned Correctly");
                    }
                    msg.setPaymentPrice(price);
                    msg.setTotalPrice(price);
                }
            }
        } else {
            throw new Exception("Factor Information Not Assigned");
        }
    }
    private JSONObject jsonParser(String strData) throws Exception{
        if(!strData.equals("")){
            JSONObject jsonObject = new JSONObject(strData);
            return jsonObject.getJSONObject("posts");
        }
        return null;
    }
    private String readData(String strUrl){
        LTH.dLog(WMH.WEBSERVICE, TAG + " -> readData, Address : " + strUrl);
        // ========== Server Communication part - it's relatively long but uses standard methods
        // ========== Encoded String - we will have to encode string by our custom method (Very easy)
        String outPut = "";
        String attachmentName = "image";
        String attachmentFileName = "";
        String crlf = "\r\n";
        String twoHyphens = "--";
        String boundary = "*****";
        int bytesRead = 0, bytesAvailable, bufferSize;
        int maxBufferSize = WMH.MAX_BUFFER_SIZE;
        /*if(imageAddress.contains("/")){
            attachmentFileName = imageAddress.substring(imageAddress.lastIndexOf("/")+1, imageAddress.length());
        }*/
        attachmentFileName = imageAddress;
        LTH.dLog(WMH.WEBSERVICE, TAG + " -> Attachment Name : " + attachmentName);
        try{
            HttpURLConnection httpUrlConnection = null;
            URL url = new URL(strUrl);
            httpUrlConnection = (HttpURLConnection) url.openConnection();
            httpUrlConnection.setUseCaches(false);
            httpUrlConnection.setDoInput(true);
            httpUrlConnection.setDoOutput(true);
            httpUrlConnection.setRequestMethod("POST");
            // httpUrlConnection.setRequestProperty("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.155 Safari/537.36");
            httpUrlConnection.setRequestProperty("Connection", "Keep-Alive");
            httpUrlConnection.setRequestProperty("Cache-Control", "no-cache");
            httpUrlConnection.setRequestProperty("ENCTYPE", "multipart/form-data");
            httpUrlConnection.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
            if(imageAddress.length() > 4) {
                httpUrlConnection.setRequestProperty(attachmentName, attachmentFileName);
            }
            DataOutputStream request = new DataOutputStream(httpUrlConnection.getOutputStream());
            request.writeBytes(twoHyphens + boundary + crlf);
            if(imageAddress.length() > 4) {
                request.writeBytes("Content-Disposition: form-data; name=\"" + attachmentName + "\";filename=\"" + attachmentFileName + "\"" + crlf);
                request.writeBytes("Content-Type: image/*" + crlf);
                request.writeBytes(crlf);

                /*BitmapFactory.Options options = new BitmapFactory.Options();
                options.inPreferredConfig = Bitmap.Config.ARGB_8888;
                Bitmap bitmap = BitmapFactory.decodeFile(imageAddress, options);
                byte[] pixels = new byte[bitmap.getWidth() * bitmap.getHeight()];
                for (int i = 0; i < bitmap.getWidth(); ++i) {
                    for (int j = 0; j < bitmap.getHeight(); ++j) {
                        //we're interested only in the MSB of the first byte, since the other 3 bytes are identical for B&W images
                        pixels[i + j] = (byte) ((bitmap.getPixel(i, j) & 0x80) >> 7);
                    }
                }
                request.write(pixels);*/

                // Code ...
                FileInputStream fileInputStream = new FileInputStream(attachmentFileName);
                bytesAvailable = fileInputStream.available();
                bufferSize = Math.min(bytesAvailable, maxBufferSize);
                byte[] buffer = new byte[bufferSize];

                // read file and write it into form...
                bytesRead = fileInputStream.read(buffer, 0, bufferSize);

                while (bytesRead > 0) {

                    request.write(buffer, 0, bufferSize);
                    bytesAvailable = fileInputStream.available();
                    bufferSize = Math.min(bytesAvailable, maxBufferSize);
                    bytesRead = fileInputStream.read(buffer, 0, bufferSize);
                }
                // Code .

                request.writeBytes(crlf);
                request.writeBytes(twoHyphens + boundary + crlf);
            }

            // Added To Send Parameters
            for(int i=0; i<parameters.size();i++){
                String key = parameters.get(i).getTitle();
                String value = "";

                try {
                    value = URLEncoder.encode(parameters.get(i).getContent(), "UTF-8");
                } catch (UnsupportedEncodingException e) {
                    LTH.eLog(TAG, e.getMessage(), e);
                    value = parameters.get(i).getContent();
                }

                LTH.dLog(WMH.WEBSERVICE, TAG + " -> " + key + " : " + value);
                request.writeBytes("Content-Disposition: form-data; name=\""+key+"\"" + crlf);
                request.writeBytes(crlf);
                request.writeBytes(value);
                request.writeBytes(crlf);
                request.writeBytes(twoHyphens + boundary + crlf);
            }

            // request.writeBytes(twoHyphens + boundary + twoHyphens + crlf);

            request.flush();
            request.close();

            int responseCode = httpUrlConnection.getResponseCode();
            LTH.dLog(WMH.WEBSERVICE, TAG + " -> Response Code : " + responseCode + " , Response Message : " + httpUrlConnection.getResponseMessage());
            if (responseCode == HttpsURLConnection.HTTP_OK) {
                InputStream responseStream = new BufferedInputStream(httpUrlConnection.getInputStream());

                BufferedReader responseStreamReader = new BufferedReader(new InputStreamReader(responseStream, Charset.forName("UTF-8")));

                String line = "";
                while ((line = responseStreamReader.readLine()) != null) {
                    outPut+=line;
                }
                responseStreamReader.close();
            }

            httpUrlConnection.disconnect();
        } catch (Exception exception){
            LTH.dLog(WMH.WEBSERVICE, TAG + " -> Error String OUTPUT Result : " + exception.getMessage(), exception);
            return exception.toString();
        }
        LTH.dLog(WMH.WEBSERVICE, TAG + " -> String OUTPUT Result : " + outPut);
        return outPut;
    }
}

php :

    $item = new stdclass();
    $item->image = $_FILES['image'];

    $imageFileType = pathinfo($_FILES['image'],PATHINFO_EXTENSION);
    $check = getimagesize($_FILES['image']["tmp_name"]);
    if($check !== false) {
        $item->file_status = "File is an image - " . $check["mime"] . ".";
    } else {
        $item->file_status = "File is not an image.";
    }

$item->imageFileType = $imageFileType;
$item->file_check = $check;

$results_array['msg'] = 'Test';
$results_array['status'] = false;
$results_array['result'] = $item;

echo $ws->unicodeString(json_encode(array('posts'=>($results_array))), 'UTF-8');

Parameter receive successfully with file, But Remember attachmentFileName if full file path .

Hossein Kurd
  • 3,184
  • 3
  • 41
  • 71

1 Answers1

9

I have written a blog on Multipart request in Android. I have clearly explained the structure of the multipart request, what every single text in the body means, how to construct one on your own in android (with code) and also how it resembles with the one that gets generated automatically when you hit the post service from browsers like firefox and finally how to consume the webrequest in JSP and java rest API. Have a glance :) Is Multipart request complicated? Think again.

EDIT

First thing first :) As name suggests multipart form data is nothing but a single request containing multiple parts in it :) Example: here is a multipart request generated by firefox :)

------WebKitFormBoundaryQHJL2hsKnlU26Mm3
Content-Disposition: form-data; name="profilePic"; filename="66.jpg"
Content-Type: application/octet-stream

//your image data appears here
------WebKitFormBoundaryQHJL2hsKnlU26Mm3
Content-Disposition: form-data; name="testingName"

Myfile.jpg //file name sent as parameter you can pass whatever parameter you want :)
------WebKitFormBoundaryQHJL2hsKnlU26Mm3--

Can you see that??? There are two parts one contains a jpg file and other contains a string (form data) :)

In your case one part will contain the image and others will contain the rest of the parameters. So in order to inform the server which part contains what you will have to create request in proper format :) In your case first part lets assume image so.

DataOutputStream dos = new DataOutputStream(con.getOutputStream());
dos.writeBytes(twoHyphens + boundary + lineEnd);

dos.writeBytes("Content-Disposition: form-data; name=\"image\";filename=\"" + imageAddress +"\"" + lineEnd);

dos.writeBytes("Content-Type: image/jpeg" + lineEnd);
dos.writeBytes(lineEnd);
dos.write(byteArray);//your image array here buddy
dos.writeBytes(lineEnd);
dos.writeBytes(twoHyphens + boundary + lineEnd);
dos.writeBytes("Content-Disposition: form-data; name=\"your parameter name\"" + crlf);
dos.writeBytes(lineEnd);
dos.writeBytes(testName);//your parameter value
dos.writeBytes(lineEnd); //to add multiple parameters write Content-Disposition: form-data; name=\"your parameter name\"" + crlf again and keep repeating till here :)
dos.writeBytes(twoHyphens + boundary + twoHyphens);
dos.flush();
dos.close();

Did you see what you were missing yes its content-type :) afterspecifying content-type you will need to enter a line end (can you see the firefox generated multipart form request)

After specifying image content you need to start the second section so enter the new line again :) Then specify the beginning of new section with twoHyphens + boundary + crlf Specify the content type again :) with Content-Disposition: form-data; name=\"your parameter name\

Enter the new line add the parameter and enter the new line again and close the section with new line again.

Repeat it untill you add all your parameter (seriously I prefer creating json of all parameter and sending it as one section) and then close multipart request with twoHyphens + boundary + twoHyphens

Thats it :) Did you get your error now?? :)

Summary : You will have to create a multipart-formdata request in such a way that it exactly matches the structure of the multipart-formdata I posted from fire fox browser :)

So if you see whatever the code I posted am doing nothing more than following the template and adding texts as per the template :) believe me server under stands it because browsers wont make mistakes you know :)

Still have a doubt ask me :) am here to help. And the code above I pasted isn't just a logical one its actually from the working code :)

Sandeep Bhandari
  • 19,999
  • 5
  • 45
  • 78
  • it only send image to server, i want to send Parameters and Image – Hossein Kurd Mar 07 '16 at 12:53
  • @AndroSco if you have seen the code correctly you will notice that I am creating two sections in message body. First section in message body has "Content-Type: image/jpeg" + crlf and image content in binary :) and the second part has a parameter named testName :) So I am sending two things one is image and a string which is the name of the person – Sandeep Bhandari Mar 07 '16 at 12:59
  • I wanted you to read it because I wanted you to understand the structure of multipart message body :) There are certain issues I found in your code lemme point out :) might help you :) – Sandeep Bhandari Mar 07 '16 at 13:00
  • I am updating my anser now please have look – Sandeep Bhandari Mar 07 '16 at 13:03
  • byte[] byteArray = stream.toByteArray(); // stream UndeFined – Hossein Kurd Mar 08 '16 at 06:17
  • i dont understand Snippet class, did you used it? – Hossein Kurd Mar 08 '16 at 06:43
  • Snippet is just a part of the working code bro :) it is not complete code :) you cant use it as it is :) it is just for understanding :) – Sandeep Bhandari Mar 08 '16 at 06:52
  • Did you undertsnad the structure of message body??? Did you see what you were missing in your code ??? like content type declaring boundary after each section new line after each section and all those stuff??? stream.toByteArray() am using to read image from file :) So you can neglect it just follow whatever is easy to u and get the byte array of the image :) and testingName is the name of the parameter i mean am looking for parameter called testingName in my server script and sandeep.jpg is a text value for that parameter :) I mean you can send image and text in single request body :) – Sandeep Bhandari Mar 08 '16 at 06:55
  • 1
    Just see the message template carefully, the one I posted from firefox and create your request body similarly (look into my code for reference like (twoHyphens + boundary + lineEnd all those things I wrote) believe me once you get it, you can write it very easily :) – Sandeep Bhandari Mar 08 '16 at 06:59
  • You can try using the code I wrote in this answer itself to send image and one parameter :) It will work i guess – Sandeep Bhandari Mar 08 '16 at 07:02