通过HTTPS POST将文件发送到远程

时间:2017-08-31 08:12:55

标签: android ssl https file-transfer

我需要使用SSL将压缩数据库(有效负载~10 MB)发送到PHP Web服务。

代码工作好几周,但我突然得到一个ssl broken pipe exceptionSSL Broken Pipe)。我没有看到任何错误原因 - 我没有更改代码,服务器配置仍然相同(IIS之前能够通过ssl处理数据传输)。

目前我使用的是java.net.HttpsURLConnection(下面的代码) - 当您将文件从Android发送到网络服务时,您建议我使用哪种替代方案?似乎没有在设备上处理POST。

提前致谢

try {
    final File compressedDb = new File(Environment.getExternalStorageDirectory() + "/" + Const.TMP_DIR + "/database.zip");
    String sourceFileUri = compressedDb.getPath();

final long compressedDbSize = compressedDb.length();
float optimized = ((float) _dbSize / (float) compressedDbSize) * 100f;
int dbKb = (int) (((float) _dbSize) / 1024f);
int dbCompKb = (int) ((float) compressedDbSize / 1024f);
compressionInfo = getString(R.string.compression) + ": " +
        dbKb + "kB " + getString(R.string.to) + " " + dbCompKb + "kB" + "<br>" +
        getString(R.string.saved) + ": " + (int) optimized + "%" + "<br>";

Log.i(TAG, "DB name=" + compressedDb.getName() + " size=" + compressedDb.length() / 1024 + "kB.");

HttpsURLConnection connection;
DataOutputStream dos;
String lineEnd = "\r\n";
String twoHyphens = "--";
String boundary = "*****";
int bytesRead, bytesAvailable, bufferSize;
byte[] buffer;
File sourceFile = new File(sourceFileUri);
//                int maxBufferSize = 1024 * 1024;
int maxBufferSize = (int) sourceFile.length();

if (sourceFile.isFile()) {

    try {

        // open a URL connection to the Servlet
        FileInputStream fileInputStream = new FileInputStream(sourceFile);
        url = new URL(params[0]);

connection = (HttpsURLConnection) url.openConnection();
connection.setDoInput(true); // Allow Inputs
connection.setUseCaches(false); // Don't use a Cached Copy
connection.setRequestMethod("POST");
connection.setRequestProperty("Connection", "Keep-Alive");
connection.setRequestProperty("ENCTYPE", "multipart/form-data");
connection.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
connection.setRequestProperty("the_database", sourceFileUri);

        dos = new DataOutputStream(connection.getOutputStream());

        dos.writeBytes(twoHyphens + boundary + lineEnd);
        dos.writeBytes("Content-Disposition: form-data; name=\"the_database\";" +
                "filename=\"" + sourceFileUri + "\"" + lineEnd);

        dos.writeBytes(lineEnd);

        // create a buffer of maximum size
        bytesAvailable = fileInputStream.available();

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

        // read file and write it into form...
        bytesRead = fileInputStream.read(buffer, 0, bufferSize);

        int bytesTotal = bytesAvailable;

        Log.i(TAG, "maxBuffer=" + maxBufferSize +
                " | bytesTotal=" + bytesTotal + " | bytesAvailable=" + bytesAvailable);

        while (bytesRead > 0) {
            dos.write(buffer, 0, bufferSize);
            bytesAvailable = fileInputStream.available();
            bufferSize = Math.min(bytesAvailable, maxBufferSize);
            bytesRead = fileInputStream.read(buffer, 0, bufferSize);
            int progress = 100 - (int) (((float) bytesAvailable * 100 / (float) bytesTotal));
            publishProgress("" + progress);
        }

        // send multipart form data necessary after file data...
        dos.writeBytes(lineEnd);
        dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);

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

        fileInputStream.close();
        dos.flush();
        dos.close();

        if (responseMessagePostDb != null) {
            responseStrings.add("<br>");
            responseStrings.add("<b><u>" + getString(R.string.optimisation_string) + "</u></b>" + "<br>");
            responseStrings.add(params[1]);

            responseStrings.add("<b><u>" + getString(R.string.optimisation_database) + "</u></b>" + "<br>");
            responseStrings.add(compressionInfo);

            String response = (responseMessagePostDb.equals("OK") ? ("<font color=\"" + GREEN + "\">PASSED</font>") : "FAILED");

            responseStrings.add(getString(R.string.server_response) + ": " + response);
            return responseStrings;
            }

        } catch (Exception e) {
            Log.e(TAG, "doInBackground: " + e.getMessage());
            responseStrings.add("FAILED2"); // <- this exception is thrown
            responseStrings.add(e.getMessage());
            return responseStrings;
        }
    }
} catch (Exception ex) {
    Log.e(TAG, "doInBackground: " + ex.getMessage());
    responseStrings.add("FAILED3");
    responseStrings.add(ex.getMessage());
    return responseStrings;
}

Log.e(TAG, "doInBackground: " + "FAILED4");
responseStrings.add("FAILED4");
responseStrings.add("Unexpected Error...");
return responseStrings;

1 个答案:

答案 0 :(得分:1)

如果您的代码到目前为止,那么从逻辑上讲,除非您的代码中存在争用条件,否则您不会看到不一致的结果,除非它不是代码。换句话说,如果服务器决定强制实施连接超时,那么您的代码似乎无理由地开始失败。甚至涉及SSL Broken Pipe异常的问题的链接似乎暗示原因是服务器,而不是客户端。

我的建议是尝试提出各种原因导致服务器执行不应该做的事情,然后通过更改代码来测试每个理论。换句话说,如果问题是超时问题,请对操作计时并通过网络发送较小的文件并验证是否有效。如果确实如此,那就有问题了。如果它没有,那么继续下一个理论。

不幸的是,上述代码没有问题,如果不了解更多详细信息,就会导致此问题无法解决。