Android image corruption when uploading via http

2.5k views Asked by At

When I upload image from android device (v 2.2) to a server (apache with php) basically, have same problem as here: Android Development Image Upload Corrupted

At first, the upload method was based on apache httpcomponent 4.1 and i thought the problem was in it. Then I have written my own upload library based on HttpURLConnection.

I tried to use different servers, but it is still the same.

Example:
http://pixelbirthcloud.com/corrupted_images/1_orig.jpg - the original image
http://pixelbirthcloud.com/corrupted_images/1_corrupted.jpg - what we get on server.

File size is the same, but the content in the content there is a corrupted block of bytes:

00051330 |       49 69 11 4B 9D E6 | 00051330 |       DA BB 10 70 DC 77 |  
00051338 | 2D B9 1B B9 E4 81 5A E6 | 00051338 | AC 20 C7 90 7E B4 33 80 |  
00051340 | D4 14 B0 F4 EA 3D D1 E9 | 00051340 | 31 9A B8 C2 29 83 66 9C |  
00051348 | 61 9D E3 38 F7 36 DE 63 | 00051348 | 9A 84 8E 73 9A 8D B5 29 |  
00051350 | 25 9D 9D C4 64 C3 23 AA | 00051350 | 18 60 1C 0F 7A CF 33 01 |  
00051358 | 4A EB 08 C3 97 7C 8C 36 | 00051358 | D4 F0 7A D3 24 BA 85 71 |  
00051360 | 73 F5 E3 15 14 5B BC C1 | 00051360 | F3 0A 76 8A D6 C4 36 5E |  
00051368 | B9 A4 49 06 71 1B 11 87 | 00051368 | 7B B9 5F 20 E3 A5 46 F2 |  
00051370 | 39 E7 76 7B 8F 5F       | 00051370 | B8 1D 4E 6B 36 6D       |

I don't know what it depends on, but on my clients' devices the images get much more corrupted. Sometimes it uploads fine, but most of the time the uploaded images are corrupted.

So I guess it's not about the http transfer. it is something about getting stream from sd card to memory and then saving that stream to http...

The code is below.

Do you guys have any ideas? Tried everything and still it doesn't' work.

public String execute() throws IOException {
    String lineEnd = "\r\n";
    String twoHyphens = "--";
    String boundary = "*****MultipartBoundary";

    try {
        URL url = new URL(mUri);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();

        conn.setDoInput(true);
        conn.setDoOutput(true);
        conn.setUseCaches(false);
        conn.setRequestMethod("POST");
        conn.setRequestProperty("Connection", "Keep-Alive");
        conn.setRequestProperty("Content-Type",
                "multipart/form-data; boundary=" + boundary);

        // timeouts
        conn.setConnectTimeout(CONNECT_TIMEOUT);
        conn.setReadTimeout(READ_TIMEOUT);

        Log.d(TAG, "Opening connectionStream");
        DataOutputStream dos = new DataOutputStream(conn.getOutputStream());

        Log.d(TAG, "Adding params");
        for (NameValuePair param : mParams) {
            dos.writeBytes(twoHyphens + boundary + lineEnd);
            dos.writeBytes("Content-Disposition: post-data; name="
                    + param.getName() + lineEnd);
            dos.writeBytes(lineEnd);
            dos.writeBytes(param.getValue());
            dos.writeBytes(lineEnd);
        }

        File file;
        Log.d(TAG, "Adding files");
        for (NameValuePair param : mFiles) {
            file = new File(param.getValue());
            if (file.exists()) {
                dos.writeBytes(twoHyphens + boundary + lineEnd);
                dos.writeBytes("Content-Disposition: post-data; name="
                        + param.getName() + "; filename=" + file.getName()
                        + lineEnd);
                dos.writeBytes("Content-Type: application/octet-stream" + lineEnd);
                dos.writeBytes("Content-Transfer-Encoding: binary" + lineEnd);
                dos.writeBytes(lineEnd);

                Log.d(TAG, "Opening fileInputStream");
                FileInputStream fileStream = new FileInputStream(file);
                try {
                    int bytesAvailable;

                    while((bytesAvailable = fileStream.available()) > 0)
                    {
                        int bufferSize = Math.min(bytesAvailable, 4096);
                        byte[] buffer = new byte[bufferSize];
                        int bytesRead = fileStream.read(buffer, 0, bufferSize);
                        dos.write(buffer, 0, bytesRead);
                    }
                    dos.writeBytes(lineEnd);
                } finally {
                    fileStream.close();
                }
                Log.d(TAG, "Closing fileINputStream");
            }
        }

        // very important - we specify the end of the multipart block
        dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);

        dos.flush();
        dos.close();

        // getting response
        if (conn.getResponseCode() == HttpStatus.SC_OK) {
            BufferedInputStream bis = new BufferedInputStream(conn.getInputStream());
            try {
                 ByteArrayBuffer baf = new ByteArrayBuffer(50);
                 int read = 0;
                 int bufSize = 512;
                 byte[] buffer = new byte[bufSize];
                 while(true){
                      read = bis.read(buffer);
                      if(read==-1){
                           break;
                      }
                      baf.append(buffer, 0, read);
                 }
                 Log.d(TAG, "Connection successful - returning result");
                 return new String(baf.toByteArray(), "UTF-8");
            } finally {
                bis.close();
            }
        } else {
            Log.d(TAG, "Return code is " + Integer.toString(conn.getResponseCode()));
            throw new IOException("Return code is " + Integer.toString(conn.getResponseCode()));
        }

    } catch (MalformedURLException e) {
        Log.e(TAG, "Exception: " + e.getMessage(), e);
        throw new IOException("aaa");
    } catch (IOException e) {
        Log.e(TAG, "Exception: " + e.getMessage(), e);
        throw new IOException();
    }
}

UPDATES:
thought about data corruption when creating streams.. so i changed a code a bit to save the file from the source stream:

                FileOutputStream fileOutStream = new FileOutputStream(AndorraApplication.getPhotosPath() + "/orig_" +file.getName() );
                DataOutputStream dataOutStream = new DataOutputStream(fileOutStream);


                try {
                    int bytesAvailable;

                    while((bytesAvailable = fileStream.available()) > 0)
                    {
                        int bufferSize = Math.min(bytesAvailable, 4096);
                        byte[] buffer = new byte[bufferSize];
                        int bytesRead = fileStream.read(buffer, 0, bufferSize);
                        dos.write(buffer, 0, bytesRead);
                        dataOutStream.write(buffer, 0, bytesRead);
                    }
                    dos.writeBytes(lineEnd);
                } finally {
                    fileStream.close();
                    dataOutStream.close();
                }

And it comes that while the uploaded image is corrupted, the image stored using dataOutStream is good... completely lost now.

is there a bug in HTTPUrlConnection on Froyo or something?

1

There are 1 answers

0
Rohit Sharma On

check i answer here how to upload a file(let it be a image file from memory or any file) to a server..

Android httpclient file upload data corruption and timeout issues

it worked great for me for uploading image.