通过 http 上传时 Android 图片损坏

标签 android http upload stream corrupt

当我将图像从 android 设备 (v 2.2) 上传到服务器 (apache with php) 基本上,这里有同样的问题:Android Development Image Upload Corrupted

一开始,上传方式是基于apache httpcomponent 4.1,我以为是它的问题。然后我自己写了一个基于HttpURLConnection的上传库。

我尝试使用不同的服务器,但还是一样。

例子:
http://pixelbirthcloud.com/corrupted_images/1_orig.jpg - 原图
http://pixelbirthcloud.com/corrupted_images/1_corrupted.jpg - 我们在服务器上得到了什么。

文件大小相同,但内容中的内容有一个损坏的字节 block :

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       |

我不知道它取决于什么,但在我客户的设备上,图像会变得更加损坏。有时上传正常,但大多数时候上传的图像已损坏。

所以我想这与 http 传输无关。它是关于从 SD 卡获取流到内存,然后将该流保存到 http...

代码如下。

你们有什么想法吗?什么都试过了,还是不行。

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();
    }
}

更新:
创建流时考虑到数据损坏..所以我稍微更改了代码以从源流中保存文件:

                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();
                }

结果是,虽然上传的图像已损坏,但使用 dataOutStream 存储的图像是好的……现在完全丢失了。

Froyo 上的 HTTPUrlConnection 是否存在错误?

最佳答案

检查我在这里回答如何将文件(让它是内存中的图像文件或任何文件)上传到服务器..

Android httpclient file upload data corruption and timeout issues

它对我上传图片非常有用。

关于通过 http 上传时 Android 图片损坏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4920912/

相关文章:

android - 如何添加通知计数器 Android

android - FragmentManager 已经在执行事务

c# - 从 URL 获取图像但未完全加载

android - 您上传了一个可调试的 APK。出于安全原因,您需要先禁用调试,然后才能将其发布到 Google Play-Upload apk to google play

java - Android 应用程序中 key 的反黑客解决方案?

delphi - 如何使用 TIdHTTPServer 和 OpenSSL 在同一端口上支持 SSL 和非 SSL 流量?

jquery - 提交自动完成的最佳格式?

upload - 谷歌云存储 - 如何限制用户上传的大小?

php - 调试由 jQuery 调用的 PHP 文件

java - TabLayout 不显示