1

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.

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. 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();
        }
    }
}
Grokify
  • 15,092
  • 6
  • 60
  • 81
David
  • 3,971
  • 1
  • 26
  • 65

1 Answers1

1

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).

harvyS
  • 628
  • 7
  • 9