Uploading parameters and image via HttpURLConnection to a PHP server (Android)

11,459

Finally got it to work...

The line "connection.setChunkedStreamingMode(1024);" is causing the problem. After removing that, the upload of parameters and file succeeded. One minor issue remains, the progress of the upload is not accurate. The progress returned is actually the buffer being filled up which is almost instantaneous even for a 3MB image. The file is still being uploaded in the background after the progress reaches 100. Guess that will be another question for another time.

Share:
11,459

Related videos on Youtube

dionkta
Author by

dionkta

Updated on July 04, 2022

Comments

  • dionkta
    dionkta almost 2 years

    Scenario: I'm trying to send some POST data via HttpURLConnection in a service (with progress updates). I am grabbing an image from the gallery and then sending it to a php server with 2 parameters; invnum and password.

    Note: If I'm doing it by the HttpClient method, the parameters and the image are sent and received in the server but I can't track the upload progress. I saw some codes related to custom multipart entity, as much as possible I would like to avoid referencing a library

    I've looked into a lot of related questions in SO but can't seem to find a solution. Below are the current codes I have in my service.

    protected void onHandleIntent(Intent intent) {
        String invnum = intent.getStringExtra("invnum");
        String uploadURL = intent.getStringExtra("uploadURL");
        String imageURI = intent.getStringExtra("imageURI");
        uri = Uri.parse(imageURI);
    
        String pass = "password";
    
        //get the actual path of the image residing in the phone
        String[] filePathColumn = { MediaStore.Images.Media.DATA };
        Cursor cursor = getContentResolver().query(uri,filePathColumn, null, null, null);
        cursor.moveToFirst();
        int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
        picturePath = cursor.getString(columnIndex);
        cursor.close();
    
        ResultReceiver receiver = (ResultReceiver) intent.getParcelableExtra("receiver");
    
        //check url
        try {
            File file = new File(picturePath);
            FileInputStream fileInputStream = new FileInputStream(file);
            byte[] bytes = new byte[(int) file.length()];
            fileInputStream.read(bytes);
            fileInputStream.close();
    
            String fileName = file.getName();
    
            URL url = new URL(uploadURL);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setDoInput(true);
            connection.setDoOutput(true);
            connection.setUseCaches(false);
            connection.setConnectTimeout(30000);
            connection.setReadTimeout(30000);
            connection.setChunkedStreamingMode(1024);
            connection.setRequestMethod("POST");
            connection.setRequestProperty("Connection", "Keep-Alive");
            connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.0.10) Gecko/2009042316 Firefox/3.0.10 (.NET CLR 3.5.30729)");
            connection.setRequestProperty("image", fileName);
            connection.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
    
            DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream());
    
            //send multipart form data (required) for file
            outputStream.writeBytes("Content-Disposition: form-data; name=\"image\";filename=\"" + fileName + "\"" + lineEnd);
            outputStream.writeBytes("Content-Type: image/jpeg" + lineEnd);
            //outputStream.writeBytes("Content-Type: " + URLConnection.guessContentTypeFromName(fileName) + lineEnd);
            //outputStream.writeBytes("Content-Transfer-Encoding: binary" + lineEnd);
            //outputStream.writeBytes("Content-Type: application/octet-stream" + lineEnd);
            outputStream.writeBytes("Content-Length: " + file.length() + lineEnd);
            outputStream.writeBytes(lineEnd);
    
            int bufferLength = 1024;
            for (int i = 0; i < bytes.length; i += bufferLength) {
                // publishing the progress....
                Bundle resultData = new Bundle();
                resultData.putInt("progress" ,(int)((i / (float) bytes.length) * 100));
                receiver.send(UPDATE_PROGRESS, resultData);
    
                if (bytes.length - i >= bufferLength) {
                    outputStream.write(bytes, i, bufferLength);
                } else {
                    outputStream.write(bytes, i, bytes.length - i);
                }
            }
    
            //end output
            outputStream.writeBytes(lineEnd);
    
            //write more parameters other than the file
            outputStream.writeBytes(twoHyphens + boundary + lineEnd);
            //outputStream.writeBytes(twoHyphens + boundary + lineEnd); //less twohyphens
            outputStream.writeBytes("Content-Disposition: form-data; name=\"invnum\"" + lineEnd);
            //outputStream.writeBytes("Content-Type: text/plain; charset=UTF-8" + lineEnd);
            //outputStream.writeBytes("Content-Length: " + invnum.length() + lineEnd);
            outputStream.writeBytes(lineEnd);
            outputStream.writeBytes(invnum + lineEnd);
            outputStream.writeBytes(twoHyphens + boundary + lineEnd);
    
            outputStream.writeBytes("Content-Disposition: form-data; name=\"pass\"" + lineEnd);
            //outputStream.writeBytes("Content-Type: text/plain; charset=UTF-8" + lineEnd);
            //outputStream.writeBytes("Content-Length: " + pass.length() + lineEnd);
            outputStream.writeBytes(lineEnd);
            outputStream.writeBytes(pass + lineEnd);
            outputStream.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);
    
            // publishing the progress....
            Bundle resultData = new Bundle();
            resultData.putInt("progress", 100);
            receiver.send(UPDATE_PROGRESS, resultData);
    
            outputStream.flush();
            outputStream.close();
            //input ignored for now
    
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    

    When running the app, the progress is reflected nicely but when checking on my server, no files are uploaded at all. In fact no data is sent or received by the server. Does anyone have any idea what may be causing this problem? Below is my server code.

    $pass = $_POST['pass'];
    $invnum = $_POST['invnum'];
    $image = $_POST['image'];
    if ($pass == 'password') {
        //do something
    }
    

    Updates: For a start, I'm getting a 404 error from the HTTPURLConnection. My url looks something like "http://www.xyz.com/upload.php". Update to the former sentence, by removing "setChunkedStreamingMode", I'm able to successfully upload the parameters to the server but not the image! I'm close!

  • dionkta
    dionkta over 10 years
    This method works but it is not what I'm looking for, I cannot track the progress of the upload using HttpClient.
  • nurisezgin
    nurisezgin over 10 years
  • Brian
    Brian over 10 years
    Did you ever figure out how to solve this issue? I'm trying to do the same thing, but everyone seems to think they're tracking upload progress when they're actually just tracking the write to the butter (like you said).
  • Warpzit
    Warpzit about 9 years
    You are wrong about android httpclient methods is better. In general httpurlconnection has been improved more for newer versions of android. Read more here: android-developers.blogspot.de/2011/09/…
  • ELITE
    ELITE about 8 years
    thanks a lot dude..i was irritated of this problem from a week. finally done with your answer...really thanks a lot...