简体   繁体   English

HTTURLConnection setFixedLengthStreamingMode导致SSL中断管道异常

[英]HTTURLConnection setFixedLengthStreamingMode leads to SSL broken pipe exception

I am trying to upload a file to a REST API from Egnyte If I don't use setFixedLengthStreamingMode(...) the file is uploaded without getting exceptions, when I use setFixedLengthStreamingMode(...) I get once in while a IO/SSL Exception -> Broken pipe. 我正在尝试从Egnyte将文件上传到REST API。如果我不使用setFixedLengthStreamingMode(...),则文件上传时不会出现异常,当我使用setFixedLengthStreamingMode(...)时,我会在IO / SSL例外->管道损坏。

Why do I need this? 我为什么需要这个? As the documentation of HTTURLConnection indicates if you don't set the content length or use setChunkedStreamingMode() then the whole file would be cached in the memory of the client before sending it what is not good because if the file is too large I could get an OOM Exception. 正如HTTURLConnection的文档指出的那样,如果您不设置内容长度或使用setChunkedStreamingMode(),则整个文件将在发送之前缓存在客户端的内存中,这不好,因为如果文件太大,我会得到OOM异常。 Do you see something missing in my code? 您看到我的代码中缺少什么吗?

private Integer doFileUpload(final String urlServer, final String pathToOurFile) {
    HttpURLConnection connection = null;
    DataOutputStream outputStream = null;
    FileInputStream fileInputStream = null;

    String lineEnd = "\r\n";
    String twoHyphens = "--";
    String boundary = "*****";

    int bytesRead, fileLength, bufferSize;
    final int fileSize;
    byte[] buffer;
    int maxBufferSize = 1 * 1024 * 1024;

    try {
        File file = new File(pathToOurFile);
        fileInputStream = new FileInputStream(file);

        URL url = new URL(urlServer);
        connection = (HttpURLConnection) url.openConnection();

        String[] payload = { twoHyphens + boundary + lineEnd,
                "Content-Disposition: form-data; name=\"uploadedfile\";filename=\"" + pathToOurFile + "\"" + lineEnd, lineEnd, lineEnd,
                twoHyphens + boundary + twoHyphens + lineEnd };

        int payloadLength = 0;
        for (String string : payload) {
            payloadLength += string.getBytes("UTF-8").length;
        }
        Logger.d(TAG, "payload length: " + payloadLength);
        fileLength = fileInputStream.available();
        Logger.d(TAG, "bytes: " + fileLength);

        // Not working:
        //            connection.setFixedLengthStreamingMode(fileLength + payloadLength);

        fileSize = fileLength;

        // Allow Inputs & Outputs
        connection.setDoInput(true);
        connection.setDoInput(true);
        connection.setUseCaches(false);

        connection.setReadTimeout(5000);
        connection.setConnectTimeout(5000);

        connection.setRequestProperty("Authorization", "Bearer " + mToken);

        // Enable POST method
        connection.setRequestMethod(HttpPost.METHOD_NAME);

        //            connection.setRequestProperty("Connection", "Keep-Alive");
        connection.setRequestProperty("Connection", "close");

        // This header doesn't count to the number of bytes being sent.
        connection.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
        //            String mimeType = Utils.getMimeType(file.getName());
        //            connection.setRequestProperty("Content-Type", mimeType);

        connection.connect();
        outputStream = new DataOutputStream(connection.getOutputStream());

        outputStream.writeBytes(payload[0]);
        outputStream.writeBytes(payload[1]);
        outputStream.writeBytes(payload[2]);

        bufferSize = Math.min(fileLength, maxBufferSize);
        buffer = new byte[bufferSize];

        // Read file
        bytesRead = fileInputStream.read(buffer, 0, bufferSize);

        final int updateIntervalMilliseconds = 500; // update the UI 2 times a second
        boolean stopUploading = (FileState.UPLOADING != mFileInfo.getState() || isCancelled());
        long totalBytesRead = 0;
        long lastProgressTime = 0;

        while (bytesRead > 0 && !stopUploading)
        {
            Logger.d(TAG, "bytes read: " + totalBytesRead);
            stopUploading = (FileState.UPLOADING != mFileInfo.getState() || isCancelled());
            if (!stopUploading) {
                totalBytesRead += bytesRead;

                outputStream.write(buffer, 0, bufferSize);
                fileLength = fileInputStream.available();
                bufferSize = Math.min(fileLength, maxBufferSize);
                bytesRead = fileInputStream.read(buffer, 0, bufferSize);

                // send a progress update event in regular intervals
                long now = System.currentTimeMillis();
                if (now - lastProgressTime > updateIntervalMilliseconds) {
                    lastProgressTime = now;
                    final int percentCompleted = (int) ((totalBytesRead * 100) / fileSize);
                    if (!stopUploading && mFileInfo.getProgress() != percentCompleted) {
                        mFileInfo.sendEvent(FileEvent.UPLOAD_PROGRESS, percentCompleted);
                    }
                }
            }
        }

        outputStream.writeBytes(payload[3]);
        outputStream.writeBytes(payload[4]);

        // Responses from the server (code and message)
        int serverResponseCode = connection.getResponseCode();

        if (serverResponseCode == HttpStatus.SC_OK || serverResponseCode == HttpStatus.SC_CREATED) {
            return JBError.JBERR_SUCCESS;
        } else {
            return serverResponseCode;
        }

    } catch (SocketTimeoutException e) {
        //applayExponentialBackoff(n);
        Log.e(TAG, "SocketTimeoutException");
        return JBError.JBERR_NO_NETWORK;
    } catch (UnknownHostException e) {
        Log.e(TAG, "UnknownHostException");
        return JBError.JBERR_NO_NETWORK;
    } catch (SocketException e) {
        Log.e(TAG, "SocketException");
        return JBError.JBERR_NO_NETWORK;
    } catch (IOException e) {
        Log.e(TAG, "IOException");
        e.printStackTrace();
        return JBError.JBERR_FAILED;
    } catch (Exception ex) {
        Log.e(TAG, "Exception");
        ex.printStackTrace();
        return JBError.JBERR_FAILED;
    } finally {
        if (connection != null) {
            connection.disconnect();
        }
        try {
            if (fileInputStream != null) {
                fileInputStream.close();
            }
            if (outputStream != null) {
                outputStream.flush();
                outputStream.close();
            }

        } catch (IOException e) {
            Log.e(TAG, "IOException");
            e.printStackTrace();
        }
    }
}

The content length calculated properly? 内容长度计算正确吗? If you are not sure try instead fixed length use chunked mode. 如果不确定,请尝试使用固定长度的分块模式。 For android it something like setChunkedStreamingMode(int chunkLength). 对于android,它类似于setChunkedStreamingMode(int chunkLength)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM