HTTURLConnection Upload not 100% working

137 Views Asked by At

I am trying to upload a file to a server with following code, the upload works, but the payload is added to the file, you can see it for example uploading a text file:

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

    final String pathToOurFile = mFileInfo.getProviderPath();
    final String lineEnd = "\r\n";
    final String twoHyphens = "--";
    final String boundary = "*****";

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

    try {
        final File file = new File(pathToOurFile);

        fileInputStream = new FileInputStream(file);

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

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

        int payloadLength = 0;
        for (final String string : payload) {
            payloadLength += string.getBytes("UTF-8").length;
        }
        Logger.d(AsyncEgnyteUploadFile.LOGGING_TAG, "payload length: " + payloadLength);
        fileLength = (int) file.length();
        Logger.d(AsyncEgnyteUploadFile.LOGGING_TAG, "bytes: " + fileLength);
        connection.setFixedLengthStreamingMode(fileLength + payloadLength);
        fileSize = fileLength;

        // Allow Inputs & Outputs
        connection.setDoInput(true);
        connection.setDoOutput(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", "close");

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

        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];

        long totalBytesRead = 0;
        long lastProgressTime = 0;

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

        boolean stopUploading = (FileState.UPLOADING != mFileInfo.getState() || isCancelled());
        while (bytesToRead > 0 && !stopUploading)
        {
            outputStream.write(buffer);
            totalBytesRead += bytesToRead;
            Logger.d(AsyncEgnyteUploadFile.LOGGING_TAG, "bytes written: " + totalBytesRead);

            final long now = System.currentTimeMillis();                

            bufferSize = (int) Math.min(fileLength - totalBytesRead, maxBufferSize);
            buffer = new byte[bufferSize];
            bytesToRead = fileInputStream.read(buffer, 0, bufferSize);
        }

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

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

        if (serverResponseCode == HttpStatus.SC_OK || serverResponseCode == HttpStatus.SC_CREATED) {                
            mAlreadyUploaded = true;
            return JBError.JBERR_SUCCESS;
        } else {
            Log.e(AsyncEgnyteUploadFile.LOGGING_TAG, "error code: " + serverResponseCode);
            return serverResponseCode;
        }

    } catch (final SocketTimeoutException e) {
        ..
    } catch (final UnknownHostException e) {
        ..
    } catch (final SocketException e) {
        ..
    } catch (final IOException e) {
        ..
    } catch (final Exception ex) {
        ..
    } finally {
        closeAll(connection, fileInputStream, outputStream);
    }
}

Uploading a text file with only 12345 inside with this code results in following:

--*****
Content-Disposition: form-data; name="uploadedfile";filename="/storage/emulated/0/Download/3.txt"

12345
--*****--

What am I doing wrong?

2

There are 2 best solutions below

0
On

You copy code is wrong. This is how to copy between streams in Java:

while ((count = in.read(buffer)) > 0)
{
    out.write(buffer, 0, count);
}

Notes:

  1. You must check all reads for end of stream.
  2. You must use the read count in the write() method.
  3. You don't need a new buffer per read, and you don't need a buffer the size of the file. This will work with any buffer size greater than zero. I usually use 8192.
3
On

I suspect that your server is not designed / configured to handle "multi-part" uploads.

It certainly looks like it is treating this as a plain upload ... and I cannot see anything wring with the multi-part encapsulation.

(EJP is correct, but that is not what is causing your problem here. Your example shows that all of the characters were sent ...)