把下面的内容翻译成中文如果有html标签和引号或双引号内的内容请不要翻译: Android to PHP: epipe Broken Pipe / stream closed posting chunked multipart form-data using httpurlconnection 将Android到PHP的内容翻译成中文:epipe Broken Pipe / stream closed 使用httpurlconnection发送分块多部分表单数据时流关闭

9 浏览
0 Comments

把下面的内容翻译成中文如果有html标签和引号或双引号内的内容请不要翻译: Android to PHP: epipe Broken Pipe / stream closed posting chunked multipart form-data using httpurlconnection 将Android到PHP的内容翻译成中文:epipe Broken Pipe / stream closed 使用httpurlconnection发送分块多部分表单数据时流关闭

我在使用HttpUrlConnection从android应用程序上传视频文件到服务器并使用PHP处理时遇到了问题。通过发送多部分的post请求,可以成功上传大小为12mb的视频文件,但对于大小为16mb的文件,会出现内存不足的错误。\n我尝试通过使用setChunkedStreamingMode(1024)或使用setFixedLengthStreamingMode(contentLength)来解决内存不足的错误。然而,这会导致epipe(broken pipe)和stream closed等错误。我不知道该如何处理这些错误。\n我首先尝试使用Kevin Sawicki的http-request库,但对于大文件会出现内存不足的错误。当我尝试使用chunking或setFixedLengthStreamingMode时,会出现epipe broken pipe错误。\nAndroid代码中的AsyncTask:\n//设置post数据\nrequest = HttpRequest.post(postUrl);\n// request.chunk(1024*1024); //如果取消注释,会出现epipe broken pipe错误\nrequest.part(\"user_id\", userId);\nrequest.part(\"question_title\", title);\nrequest.part(\"question_subject\", subject);\nrequest.part(\"question_level\", level);\n//添加照片或视频\nif (mediaType == PHOTO) {\n request.part(\"file\", photoFile.getName(), photoFile);\n}\nelse if (mediaType == VIDEO) {\n request.part(\"file\", videoFile.getName(), \"video/mp4\", videoFile);\n}\nif (request.ok()) {\n try {\n return new JSONObject(request.body().toString());\n } catch (HttpRequestException e) {\n e.printStackTrace();\n } catch (JSONException e) {\n e.printStackTrace();\n }\n}\nLogCat:\n10-24 16:26:59.365: E/AndroidRuntime(19014): FATAL EXCEPTION: AsyncTask #4\n10-24 16:26:59.365: E/AndroidRuntime(19014): java.lang.RuntimeException: An error occured while executing doInBackground()\n10-24 16:26:59.365: E/AndroidRuntime(19014): at android.os.AsyncTask$3.done(AsyncTask.java:299)\n10-24 16:26:59.365: E/AndroidRuntime(19014): at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:352)\n10-24 16:26:59.365: E/AndroidRuntime(19014): at java.util.concurrent.FutureTask.setException(FutureTask.java:219)\n10-24 16:26:59.365: E/AndroidRuntime(19014): at java.util.concurrent.FutureTask.run(FutureTask.java:239)\n10-24 16:26:59.365: E/AndroidRuntime(19014): at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)\n10-24 16:26:59.365: E/AndroidRuntime(19014): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)\n10-24 16:26:59.365: E/AndroidRuntime(19014): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)\n10-24 16:26:59.365: E/AndroidRuntime(19014): at java.lang.Thread.run(Thread.java:841)\n10-24 16:26:59.365: E/AndroidRuntime(19014): Caused by: com.example.askacademy.HttpRequest$HttpRequestException: java.net.SocketException: sendto failed: EPIPE (Broken pipe)\n10-24 16:26:59.365: E/AndroidRuntime(19014): at com.example.askacademy.HttpRequest$Operation.call(HttpRequest.java:689)\n10-24 16:26:59.365: E/AndroidRuntime(19014): at com.example.askacademy.HttpRequest.copy(HttpRequest.java:2586)\n10-24 16:26:59.365: E/AndroidRuntime(19014): at com.example.askacademy.HttpRequest.part(HttpRequest.java:2899)\n10-24 16:26:59.365: E/AndroidRuntime(19014): at com.example.askacademy.HttpRequest.part(HttpRequest.java:2866)\n10-24 16:26:59.365: E/AndroidRuntime(19014): at com.example.askacademy.CreateQuestionActivity$createQuestionTask.doInBackground(CreateQuestionActivity.java:447)\n10-24 16:26:59.365: E/AndroidRuntime(19014): at com.example.askacademy.CreateQuestionActivity$createQuestionTask.doInBackground(CreateQuestionActivity.java:1)\n10-24 16:26:59.365: E/AndroidRuntime(19014): at android.os.AsyncTask$2.call(AsyncTask.java:287)\n10-24 16:26:59.365: E/AndroidRuntime(19014): at java.util.concurrent.FutureTask.run(FutureTask.java:234)\n10-24 16:26:59.365: E/AndroidRuntime(19014): ... 4 more\n10-24 16:26:59.365: E/AndroidRuntime(19014): Caused by: java.net.SocketException: sendto failed: EPIPE (Broken pipe)\n10-24 16:26:59.365: E/AndroidRuntime(19014): at libcore.io.IoBridge.maybeThrowAfterSendto(IoBridge.java:499)\n10-24 16:26:59.365: E/AndroidRuntime(19014): at libcore.io.IoBridge.sendto(IoBridge.java:468)\n10-24 16:26:59.365: E/AndroidRuntime(19014): at java.net.PlainSocketImpl.write(PlainSocketImpl.java:507)\n10-24 16:26:59.365: E/AndroidRuntime(19014): at java.net.PlainSocketImpl.access$100(PlainSocketImpl.java:46)\n10-24 16:26:59.365: E/AndroidRuntime(19014): at java.net.PlainSocketImpl$PlainSocketOutputStream.write(PlainSocketImpl.java:269)\n10-24 16:26:59.365: E/AndroidRuntime(19014): at libcore.net.http.ChunkedOutputStream.writeHex(ChunkedOutputStream.java:102)\n10-24 16:26:59.365: E/AndroidRuntime(19014): at libcore.net.http.ChunkedOutputStream.writeBufferedChunkToSocket(ChunkedOutputStream.java:128)\n10-24 16:26:59.365: E/AndroidRuntime(19014): at libcore.net.http.ChunkedOutputStream.write(ChunkedOutputStream.java:77)\n10-24 16:26:59.365: E/AndroidRuntime(19014): at java.io.BufferedOutputStream.write(BufferedOutputStream.java:131)\n10-24 16:26:59.365: E/AndroidRuntime(19014): at com.example.askacademy.HttpRequest$8.run(HttpRequest.java:2580)\n10-24 16:26:59.365: E/AndroidRuntime(19014): at com.example.askacademy.HttpRequest$8.run(HttpRequest.java:1)\n10-24 16:26:59.365: E/AndroidRuntime(19014): at com.example.askacademy.HttpRequest$Operation.call(HttpRequest.java:683)\n10-24 16:26:59.365: E/AndroidRuntime(19014): ... 11 more\n10-24 16:26:59.365: E/AndroidRuntime(19014): Caused by: libcore.io.ErrnoException: sendto failed: EPIPE (Broken pipe)\n10-24 16:26:59.365: E/AndroidRuntime(19014): at libcore.io.Posix.sendtoBytes(Native Method)\n10-24 16:26:59.365: E/AndroidRuntime(19014): at libcore.io.Posix.sendto(Posix.java:155)\n10-24 16:26:59.365: E/AndroidRuntime(19014): at libcore.io.BlockGuardOs.sendto(BlockGuardOs.java:177)\n10-24 16:26:59.365: E/AndroidRuntime(19014): at libcore.io.IoBridge.sendto(IoBridge.java:466)\n10-24 16:26:59.365: E/AndroidRuntime(19014): ... 21 more\n然后,我尝试仅发送文件而不使用任何库,使用了来自StackOverflow的代码,结果出现stream closed错误。\nAndroid代码:\nHttpURLConnection conn = null;\nDataOutputStream dos = null;\nDataInputStream inStream = null;\nString lineEnd = \"\\r\\n\";\nString twoHyphens = \"--\";\nString boundary = \"***************************************************\";\nint bytesRead, bytesAvailable, bufferSize;\nbyte[] buffer;\nint maxBufferSize = 212144; // 1024*1024 = 1MB. 212144 is a quarter MB.\nFileInputStream fileInputStream = null;\ntry {\n fileInputStream = new FileInputStream(videoFile);\n // 打开到Servlet的URL连接\n URL url = new URL(postUrl);\n // 打开到URL的HTTP连接\n conn = (HttpURLConnection) url.openConnection();\n // 允许输入\n conn.setDoInput(true);\n // 允许输出\n conn.setDoOutput(true);\n // 以块的形式发送(避免内存不足错误)\n conn.setChunkedStreamingMode(maxBufferSize); // 导致stream closed错误\n // 不使用缓存\n conn.setUseCaches(false);\n // 使用POST方法\n conn.setRequestMethod(\"POST\"); \n conn.setRequestProperty(\"Connection\", \"Keep-Alive\");\n conn.setRequestProperty(\"Content-Type\", \"multipart/form-data;boundary=\"\n + boundary);\n conn.setReadTimeout(200000); // 200秒...\n dos = new DataOutputStream(conn.getOutputStream());\n dos.writeBytes(twoHyphens + boundary + lineEnd);\n dos.writeBytes(\"Content-Disposition: form-data; name=\\\"file\\\";filename=\\\"\"\n + videoFile.getName() + \"\\\"\" + lineEnd);\n dos.writeBytes(lineEnd);\n // 创建最大尺寸的缓冲区\n bytesAvailable = fileInputStream.available();\n bufferSize = Math.min(bytesAvailable, maxBufferSize);\n buffer = new byte[bufferSize];\n // 读取文件并将其写入表单中...\n bytesRead = fileInputStream.read(buffer, 0, bufferSize);\n while (bytesRead > 0)\n {\n try {\n dos.write(buffer, 0, bufferSize); \n } catch (OutOfMemoryError oome) {\n Log.e(DEBUG_TAG, \"Out of memory error caught...\");\n oome.printStackTrace();\n fileInputStream.close();\n throw new Exception(\"Out Of Memory!\");\n }\n bytesAvailable = fileInputStream.available();\n bufferSize = Math.min(bytesAvailable, maxBufferSize);\n bytesRead = fileInputStream.read(buffer, 0, bufferSize);\n // 发送文件数据后必要的multipart form数据...\n dos.writeBytes(lineEnd);\n dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);\n fileInputStream.close();\n dos.flush();\n dos.close();\n // 关闭流\n Log.d(DEBUG_TAG, \"Backup file written to server successfully...\");\n }\n} catch (Exception e) {\n // TODO: handle exception\n e.printStackTrace();\n}\nLogcat:\n10-24 16:29:29.070: I/dalvikvm-heap(19832): Grow heap (frag case) to 23.474MB for 4147216-byte allocation\n10-24 16:29:29.090: D/dalvikvm(19832): GC_FOR_ALLOC freed 1K, 20% free 22595K/28144K, paused 20ms, total 20ms\n10-24 16:29:29.100: W/CursorWrapperInner(19832): Cursor finalized without prior close()\n10-24 16:29:30.700: D/ProgressBar(19832): setProgress = 0\n10-24 16:29:30.700: D/ProgressBar(19832): setProgress = 0, fromUser = false\n10-24 16:29:30.700: D/ProgressBar(19832): mProgress = 0mIndeterminate = false, mMin = 0, mMax = 10000\n10-24 16:29:30.770: D/CreateQuestion(19832): Backup file written to server successfully...\n10-24 16:29:30.770: W/System.err(19832): java.io.IOException: stream closed\n10-24 16:29:30.775: W/System.err(19832): at libcore.net.http.AbstractHttpOutputStream.checkNotClosed(AbstractHttpOutputStream.java:37)\n10-24 16:29:30.775: W/System.err(19832): at libcore.net.http.ChunkedOutputStream.write(ChunkedOutputStream.java:65)\n10-24 16:29:30.775: W/System.err(19832): at java.io.DataOutputStream.write(DataOutputStream.java:98)\n10-24 16:29:30.775: W/System.err(19832): at com.example.askacademy.CreateQuestionActivity$createQuestionTask.doInBackground(CreateQuestionActivity.java:405)\n10-24 16:29:30.775: W/System.err(19832): at com.example.askacademy.CreateQuestionActivity$createQuestionTask.doInBackground(CreateQuestionActivity.java:1)\n10-24 16:29:30.775: W/System.err(19832): at android.os.AsyncTask$2.call(AsyncTask.java:287)\n10-24 16:29:30.780: W/System.err(19832): at java.util.concurrent.FutureTask.run(FutureTask.java:234)\n10-24 16:29:30.780: W/System.err(19832): at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)\n10-24 16:29:30.780: W/System.err(19832): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)\n10-24 16:29:30.780: W/System.err(19832): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)\n10-24 16:29:30.780: W/System.err(19832): at java.lang.Thread.run(Thread.java:841)\n10-24 16:29:30.780: W/System.err(19832): org.json.JSONException: Unterminated object at character 52 of {\"success\":\"false\",\"error\":\"Error creating question\"\n10-24 16:29:30.780: W/System.err(19832): at org.json.JSONTokener.syntaxError(JSONTokener.java:450)\n10-24 16:29:30.780: W/System.err(19832): at org.json.JSONTokener.readObject(JSONTokener.java:394)\n10-24 16:29:30.780: W/System.err(19832): at org.json.JSONTokener.nextValue(JSONTokener.java:100)\n10-24 16:29:30.780: W/System.err(19832): at org.json.JSONObject.(JSONObject.java:154)\n10-24 16:29:30.780: W/System.err(19832): at org.json.JSONObject.(JSONObject.java:171)\n10-24 16:29:30.780: W/System.err(19832): at com.example.askacademy.CreateQuestionActivity$createQuestionTask.doInBackground(CreateQuestionActivity.java:461)\n10-24 16:29:30.780: W/System.err(19832): at com.example.askacademy.CreateQuestionActivity$createQuestionTask.doInBackground(CreateQuestionActivity.java:1)\n10-24 16:29:30.780: W/System.err(19832): at android.os.AsyncTask$2.call(AsyncTask.java:287)\n10-24 16:29:30.780: W/System.err(19832): at java.util.concurrent.FutureTask.run(FutureTask.java:234)\n10-24 16:29:30.780: W/System.err(19832): at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)\n10-24 16:29:30.780: W/System.err(19832): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)\n10-24 16:29:30.785: W/System.err(19832): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)\n10-24 16:29:30.785: W/System.err(19832): at java.lang.Thread.run(Thread.java:841)\n问题是:\n如何解决chunking时连接/流关闭的问题?\n如果连接问题是由服务器端问题引起的,如何找出原因并解决?注意,upload_max_filesize为512M,所以大小不是问题。另外,12mb可以成功上传,而16mb则失败。\n我不确定如何在PHP中处理服务器端的chunked数据。对于成功上传的12mb文件,我使用move_uploaded_file($_FILES[\'file\'][\'tmp_name\'], $url)来处理它。我需要什么代码来处理chunked数据?

0
0 Comments

Android to PHP: 使用HttpURLConnection发布分块多部分表单数据时出现epipe Broken Pipe / stream closed错误

问题原因:根据官方文档,在请求体长度事先知道的情况下应调用setFixedLengthStreamingMode(len),而在长度不可预知的情况下应调用setChunkedStreamingMode(0)。

关于epipe Broken Pipe错误,需要注意的是,如果可能,Android会重用旧的套接字连接,因为在移动环境中建立连接是一项资源消耗的操作。尝试强制将POST请求执行在新的连接上:

conn.setRequestProperty("connection", "close"); // 禁用Keep Alive

(需要注意的是,Android的默认行为是将该头字段设置为true,可以通过调用System.setProperty("http.keepAlive", "false");来更改)

解决方法:按照上述说明,根据请求体长度是否已知调用setFixedLengthStreamingMode(len)或setChunkedStreamingMode(0)方法,并通过设置请求头字段connection为close禁用Keep Alive来强制执行POST请求在新连接上。

感谢这个答案,它解决了我的类似问题。我花了3天时间才解决这个问题,真希望我早点找到这篇文章。

0