Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make a POST request with file and text from an Android application

I am having some problems making a proper POST request from my Android application to my web service (Google Cloud and PHP).

When I try to send an image from Android, it returns a "200 OK" response, but the image is not saved in the bucket on Google Cloud Storage. I know that the problem lies with the POST request from my method in the Android app, as I have tested with Postman and made it work without any trouble. So something is wrong in the following piece of code from my app:

public void uploadFile(String uploadUrl, String filename, String newFileName) throws IOException {
        FileInputStream fileInputStream = new FileInputStream(new File(filename));

        URL url = new URL(uploadUrl);
        connection = (HttpURLConnection) url.openConnection();

        // Allow Inputs & Outputs.
        connection.setDoInput(true);
        connection.setDoOutput(true);
        connection.setUseCaches(false);

        // Set HTTP method to POST.
        connection.setRequestMethod("POST");
        connection.setRequestProperty("Connection", "Keep-Alive");
        connection.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);

        outputStream = new DataOutputStream(connection.getOutputStream() );
        outputStream.writeBytes(twoHyphens + boundary + lineEnd);
        outputStream.writeBytes("Content-Disposition: form-data; name=\"img\";filename=\"" + filename + "\"" + lineEnd);
        outputStream.writeBytes(lineEnd);

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

        // Read file
        bytesRead = fileInputStream.read(buffer, 0, bufferSize);

        while (bytesRead > 0) {
            outputStream.write(buffer, 0, bufferSize);
            bytesAvailable = fileInputStream.available();
            bufferSize = Math.min(bytesAvailable, maxBufferSize);
            bytesRead = fileInputStream.read(buffer, 0, bufferSize);
        }

        outputStream.writeBytes(lineEnd);
        outputStream.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);

        // Responses from the server (code and message)
        int serverResponseCode = connection.getResponseCode();
        String serverResponseMessage = connection.getResponseMessage();


        System.out.println(serverResponseMessage);
        System.out.println(serverResponseCode);


        fileInputStream.close();
        outputStream.flush();
        outputStream.close();
    }

I have already tested that all of the parameters are 100% correct, so you don't need to worry about that.

In case you should need to see the PHP code from the web service for receiving the request, here it is:

<?php
$img = $_FILES['img']['tmp_name'];
move_uploaded_file($img, 'gs://routeimages/yeeeeeeees.jpg');

echo "done";

?>

Where might the problem be in this code?

Additional

I also need to add some text besides the file/image. How can I add this to the request?

like image 455
Langkiller Avatar asked Sep 25 '22 16:09

Langkiller


2 Answers

Looks like you are missing Content-type of image file you are sending.

Have a look at following HTTP Post header for sending file

Content-type: multipart/form-data, boundary=AaB03x
    --AaB03x
    content-disposition: form-data; name="pics", filename="file2.gif"
    Content-type: image/gif
    Content-Transfer-Encoding: binary

    ...contents of file2.gif...
    --AaB03x--

So you need to add Content-type property in you code like following:

outputStream = new DataOutputStream(connection.getOutputStream() );
outputStream.writeBytes(twoHyphens + boundary + lineEnd); 
outputStream.writeBytes("Content-Disposition: form-data; name=\"img\";filename=\"" + filename + "\"" + lineEnd);
outputStream.writeBytes("Content-type: image/gif" + lineEnd); // or whatever format you are sending.
outputStream.writeBytes("Content-Transfer-Encoding: binary" + lineEnd); 
outputStream.writeBytes(lineEnd);

I hope this piece of code should get you through your problem.

Additional: I also need to add some text besides the file/image. How can I add this to the request? For sending some extra parameters(Some text) have a look at following http format that is sending image along with a text parameter:

    Content-type: multipart/form-data, boundary=AaB03x
    --AaB03x
    content-disposition: form-data; name="pics", filename="file2.gif"
    Content-type: image/gif
    Content-Transfer-Encoding: binary

    ...contents of file2.gif...
    --AaB03x--
    content-disposition: form-data; name="field1"

    Joe Blow
    --AaB03x

I hope you can now write code for extra parameter with the help of above image upload explanation and this format.

like image 195
chandil03 Avatar answered Oct 17 '22 15:10

chandil03


Why not using the Volley lib ? Its way easier and clean. Like this example:

private void uploadImage(){
        //Showing the progress dialog
        final ProgressDialog loading = ProgressDialog.show(this,"Uploading...","Please wait...",false,false);
        StringRequest stringRequest = new StringRequest(Request.Method.POST, UPLOAD_URL,
                new Response.Listener<String>() {
                    @Override
                public void onResponse(String s) {
                    //Disimissing the progress dialog
                    loading.dismiss();
                    //Showing toast message of the response
                    Toast.makeText(MainActivity.this, s , Toast.LENGTH_LONG).show();
                }
            },
            new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError volleyError) {
                    //Dismissing the progress dialog
                    loading.dismiss();

                    //Showing toast
                    Toast.makeText(MainActivity.this, volleyError.getMessage().toString(), Toast.LENGTH_LONG).show();
                }
            }){
        @Override
        protected Map<String, String> getParams() throws AuthFailureError {
            //Converting Bitmap to String
            String image = getStringImage(bitmap);

            //Getting Image Name
            String name = editTextName.getText().toString().trim();

            //Creating parameters
            Map<String,String> params = new Hashtable<String, String>();

            //Adding parameters
            params.put(KEY_IMAGE, image);
            params.put(KEY_NAME, name);

            //returning parameters
            return params;
        }
    };

    //Creating a Request Queue
    RequestQueue requestQueue = Volley.newRequestQueue(this);

    //Adding request to the queue
    requestQueue.add(stringRequest);
}

Source

like image 35
Carlos Avatar answered Oct 17 '22 13:10

Carlos