【问题标题】:Unable to upload zip file from Android to server sendto failed: epipe (broken pipe)无法将 zip 文件从 Android 上传到服务器 sendto 失败:epipe(损坏的管道)
【发布时间】:2018-02-06 05:49:00
【问题描述】:

我正在创建一个 android 应用程序,用于将 zip 文件从本地文件系统上传到服务器。下面是我的文件上传代码。

 protected Object doInBackground(Object[] objects) {
        try {
    String boundary = "===" + System.currentTimeMillis() + "===";
                String LINE_FEED = "\r\n";
                String charset;
                String fieldName = "uploadFile";
                URL url = new URL("http://hridhaanirs.com/REST-TEST/upload");
                HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
                httpConn.setUseCaches(false);
                httpConn.setDoOutput(true); // indicates POST method
                httpConn.setDoInput(true);
                httpConn.setRequestProperty( "Accept-Encoding", "" );
                httpConn.setRequestProperty("Content-Type",
                        "multipart/form-data; boundary=" + boundary);
                httpConn.setRequestProperty("User-Agent", "CodeJava Agent");
                httpConn.setRequestProperty("Test", "Bonjour");
                OutputStream outputStream = httpConn.getOutputStream();
                PrintWriter writer = new PrintWriter(new OutputStreamWriter(outputStream, "UTF-8"),
                        true);
                outputStream = httpConn.getOutputStream();
                File file=new File((String)objects[0]);
                String fileName = file.getName();
                writer.append("--" + boundary).append(LINE_FEED);
                writer.append("Content-Disposition: form-data; name=\"" + fieldName
                        + "\"; filename=\"" + fileName + "\"")
                        .append(LINE_FEED);
                writer.append(
                        "Content-Type: "
                                + URLConnection.guessContentTypeFromName(fileName))
                        .append(LINE_FEED);
                writer.append("Content-Transfer-Encoding: binary").append(LINE_FEED);

                writer.append(LINE_FEED);
                writer.flush();

                FileInputStream inputStream = new FileInputStream(file);
                FileReader fileReader=new FileReader(file);
                int buff;
                while((buff=fileReader.read())!=-1){
                    outputStream.write(buff);
                }
                outputStream.flush();
                inputStream.close();

                writer.append(LINE_FEED);
                writer.flush();
                List<String> response = new ArrayList<>();
                writer.append(LINE_FEED).flush();
                writer.append("--" + boundary + "--").append(LINE_FEED);
                writer.close();

                int status = httpConn.getResponseCode();
                if (status == HttpURLConnection.HTTP_OK) {
                    BufferedReader reader = new BufferedReader(new InputStreamReader(httpConn.getInputStream()));
                    String line = null;
                    while ((line = reader.readLine()) != null) {
                        response.add(line);
                    }
                    reader.close();
                    httpConn.disconnect();
                }
                return response;
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }

执行上述代码调试时,我看到以下异常。

02-06 11:13:36.863 32495-32598/com.tech.mds.mdsconnect I/System.out: [OkHttp] sendRequest>>
02-06 11:13:41.886 32495-32598/com.tech.mds.mdsconnect W/System.err: java.net.SocketException: sendto failed: EPIPE (Broken pipe)
02-06 11:13:41.913 32495-32598/com.tech.mds.mdsconnect W/System.err:     at libcore.io.IoBridge.maybeThrowAfterSendto(IoBridge.java:586)
02-06 11:13:41.935 32495-32598/com.tech.mds.mdsconnect W/System.err:     at libcore.io.IoBridge.sendto(IoBridge.java:555)
02-06 11:13:41.957 32495-32598/com.tech.mds.mdsconnect W/System.err:     at java.net.PlainSocketImpl.write(PlainSocketImpl.java:513)
02-06 11:13:41.978 32495-32598/com.tech.mds.mdsconnect W/System.err:     at java.net.PlainSocketImpl.access$100(PlainSocketImpl.java:42)
02-06 11:13:41.998 32495-32598/com.tech.mds.mdsconnect W/System.err:     at java.net.PlainSocketImpl$PlainSocketOutputStream.write(PlainSocketImpl.java:271)
02-06 11:13:42.014 32495-32598/com.tech.mds.mdsconnect W/System.err:     at com.android.okio.Okio$1.write(Okio.java:70)
02-06 11:13:42.038 32495-32598/com.tech.mds.mdsconnect W/System.err:     at com.android.okio.RealBufferedSink.emitCompleteSegments(RealBufferedSink.java:116)
02-06 11:13:42.055 32495-32598/com.tech.mds.mdsconnect W/System.err:     at com.android.okio.RealBufferedSink.write(RealBufferedSink.java:44)
02-06 11:13:42.076 32495-32598/com.tech.mds.mdsconnect W/System.err:     at com.android.okhttp.internal.http.RetryableSink.writeToSocket(RetryableSink.java:77)
02-06 11:13:42.098 32495-32598/com.tech.mds.mdsconnect W/System.err:     at com.android.okhttp.internal.http.HttpConnection.writeRequestBody(HttpConnection.java:240)
02-06 11:13:42.119 32495-32598/com.tech.mds.mdsconnect W/System.err:     at com.android.okhttp.internal.http.HttpTransport.writeRequestBody(HttpTransport.java:77)
02-06 11:13:42.138 32495-32598/com.tech.mds.mdsconnect W/System.err:     at com.android.okhttp.internal.http.HttpEngine.readResponse(HttpEngine.java:631)
02-06 11:13:42.160 32495-32598/com.tech.mds.mdsconnect W/System.err:     at com.android.okhttp.internal.http.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:398)
02-06 11:13:42.182 32495-32598/com.tech.mds.mdsconnect W/System.err:     at com.android.okhttp.internal.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:342)
02-06 11:13:42.205 32495-32598/com.tech.mds.mdsconnect W/System.err:     at com.android.okhttp.internal.http.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:520)
02-06 11:13:42.223 32495-32598/com.tech.mds.mdsconnect W/System.err:     at com.tech.mds.mdsconnect.FileUpload.doInBackground(FileUpload.java:88)
02-06 11:13:42.240 32495-32598/com.tech.mds.mdsconnect W/System.err:     at android.os.AsyncTask$2.call(AsyncTask.java:292)
02-06 11:13:42.258 32495-32598/com.tech.mds.mdsconnect W/System.err:     at java.util.concurrent.FutureTask.run(FutureTask.java:237)
02-06 11:13:42.275 32495-32598/com.tech.mds.mdsconnect W/System.err:     at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
02-06 11:13:42.293 32495-32598/com.tech.mds.mdsconnect W/System.err:     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
02-06 11:13:42.308 32495-32598/com.tech.mds.mdsconnect W/System.err:     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
02-06 11:13:42.316 32495-32598/com.tech.mds.mdsconnect W/System.err:     at java.lang.Thread.run(Thread.java:818)
02-06 11:13:42.334 32495-32598/com.tech.mds.mdsconnect W/System.err: Caused by: android.system.ErrnoException: sendto failed: EPIPE (Broken pipe)
02-06 11:13:42.403 32495-32598/com.tech.mds.mdsconnect W/System.err:     at libcore.io.Posix.sendtoBytes(Native Method)
02-06 11:13:42.413 32495-32598/com.tech.mds.mdsconnect W/System.err:     at libcore.io.Posix.sendto(Posix.java:206)
02-06 11:13:42.423 32495-32598/com.tech.mds.mdsconnect W/System.err:     at libcore.io.BlockGuardOs.sendto(BlockGuardOs.java:278)
02-06 11:13:42.433 32495-32598/com.tech.mds.mdsconnect W/System.err:     at libcore.io.IoBridge.sendto(IoBridge.java:553)
02-06 11:13:42.438 32495-32598/com.tech.mds.mdsconnect W/System.err:    ... 20 more

ZIP 文件包含几个图像和一个 .txt 文件。如果我上传 .txt 文件,那么它可以成功。 此外,我在 JAVA SE 环境中使用了相同的代码并成功上传了相同的 zip 文件。所以肯定这似乎是一个环境问题。

【问题讨论】:

  • 使用改造和多部分。 [参考][1] 和 [this][2] [1]:futurestud.io/tutorials/… [2]:androidmads.blogspot.in/2016/06/…
  • @Umair.. 我看到了那个帖子。但是在我的情况下,我在 int status = httpConn.getResponseCode();
  • @MayankVaid 是的,这意味着您没有从正在关闭连接的服务器获得任何东西。要么你的请求有问题,要么就像答案说你超出了上传限制。
  • @Umair 上传限制应该不是问题,因为服务器已经配置为大约 1 GB 的数据。就我而言,它几乎不是 10 mb。其次,我无法理解为什么相同的代码在 Java SE 环境中运行良好。

标签: java android


【解决方案1】:
  1. 服务器已关闭连接,原因可能是您手动实现的分块协议不正确,或者您已超出上传限制。

  2. 扔掉你手工实现的分块协议,使用HttpURLConnection.setChunkedStreamingMode()

【讨论】:

  • 这里的手动卡盘协议是什么?
  • 最大大小应该不是问题,因为服务器应用程序已经配置为采用 2 GB 数据......并且相同的代码在 Java SE 环境中运行良好。
【解决方案2】:

我按照@greenapps 的建议修改了阅读代码,一切正常。似乎一次读取一个字节会使请求变得非常慢,因此连接被终止。使用缓冲区一次读取特定数量的字节并写入输出流。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-05-05
    • 1970-01-01
    • 2015-07-05
    • 2011-10-17
    • 1970-01-01
    • 2012-06-08
    • 2011-05-20
    • 1970-01-01
    相关资源
    最近更新 更多