title: Android image corruption when uploading via http
body: <p>When I upload image from android device (v 2.2) to a server (apache with php)
  basically, have same problem as here: <a href="https://stackoverflow.com/questions/3154224/android-development-image-upload-corrupted">Android Development Image Upload Corrupted</a></p>
  
  <p>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.</p>
  
  <p>I tried to use different servers, but it is still the same.</p>
  
  <p>Example:<br>
  <a href="http://pixelbirthcloud.com/corrupted_images/1_orig.jpg" rel="nofollow noreferrer">http://pixelbirthcloud.com/corrupted_images/1_orig.jpg</a> - the original image<br>
  <a href="http://pixelbirthcloud.com/corrupted_images/1_corrupted.jpg" rel="nofollow noreferrer">http://pixelbirthcloud.com/corrupted_images/1_corrupted.jpg</a> - what we get on server.</p>
  
  <p>File size is the same, but the content in the content there is a corrupted block of bytes:  </p>
  
  <pre><code>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       |
  </code></pre>
  
  <p>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.</p>
  
  <p>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...</p>
  
  <p>The code is below.</p>
  
  <p>Do you guys have any ideas? Tried everything and still it doesn't' work.</p>
  
  <pre><code>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()) &gt; 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();
      }
  }
  </code></pre>
  
  <p><strong>UPDATES:</strong><br>
  thought about data corruption when creating streams.. so i changed a code a bit to save the file from the source stream:</p>
  
  <pre><code>                FileOutputStream fileOutStream = new FileOutputStream(AndorraApplication.getPhotosPath() + "/orig_" +file.getName() );
                  DataOutputStream dataOutStream = new DataOutputStream(fileOutStream);
  
  
                  try {
                      int bytesAvailable;
  
                      while((bytesAvailable = fileStream.available()) &gt; 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();
                  }
  </code></pre>
  
  <p>And it comes that while the uploaded image is corrupted, the image stored using dataOutStream is good... completely lost now.</p>
  
  <p>is there a bug in HTTPUrlConnection on Froyo or something?</p>