0

In my application I use HttpUrlConnection to upload file to server, when I want to upload a large file, nginx give me a 413 exception code, but HttpUrlConnection's getResponseCode can't catch the exception, I got another exception message. Here is the exception message:

error asyncExecute:Write error: ssl=0x7ec7b80008: I/O error during system call, Connection reset by peer

Here is my code:

    URL originUrl = new URL(url);
    String protocol = originUrl.getProtocol();
    if (TextUtils.equals(protocol, "http")) {
        port = 80;
    }
    mURL = new URL(protocol, originUrl.getHost(), port, originUrl.getFile());
    mConn = (HttpURLConnection) mURL.openConnection();

    if (mConn instanceof HttpsURLConnection) {
        selfSignedCertificate = true;
        SSLCustomSocketFactory factory = new SSLCustomSocketFactory(selfSignedCertificate ? SSLCustomSocketFactory.getSocketFactory()
                : (SSLSocketFactory) SSLSocketFactory.getDefault());
        ((HttpsURLConnection) mConn).setSSLSocketFactory(factory);
        ((HttpsURLConnection) mConn).setHostnameVerifier(new HostnameVerifier() {
            @Override
            public boolean verify(String hostname, SSLSession session) {
                return true;
            }
        });
    }
    mConn.setRequestMethod("POST");
    mConn.setDoOutput(true);
    mConn.setDoInput(true);
    mConn.setUseCaches(false);
    mConn.setConnectTimeout(30000);
    mConn.setReadTimeout(30000);
    mConn.setRequestProperty("User-agent", "xxxx");//xxxx涉及到项目中信息不展示
    mConn.setRequestProperty("Connection", "Keep-Alive");
    mConn.setRequestProperty("Charset", "UTF-8");
    mConn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY);
    mConn.setRequestProperty("Expect", "100-Continue");
    mConn.setChunkedStreamingMode(0);
    //request headers
    for (Map.Entry<String, String> item : headers.entrySet()) {
          mConn.setRequestProperty(item.getKey(), item.getValue());
     }
    mConn.connect();
    //get outputStream
    DataOutputStream out = new DataOutputStream(connect.getOutputStream());
    //write params
    out.write(params.getBytes());
    out.flush();
    StringBuffer strBuf = new StringBuffer();
    for (String key : paramsMap.keySet()){
        strBuf.append(TWO_HYPHENS);
        strBuf.append(BOUNDARY);
        strBuf.append(LINE_END);
        strBuf.append("Content-Disposition: form-data; name=\"" + key + "\"");
        strBuf.append(LINE_END);

        strBuf.append("Content-Type: " + "text/plain" );
        strBuf.append(LINE_END);
        strBuf.append("Content-Length: "+paramsMap.get(key).length());
        strBuf.append(LINE_END);
        strBuf.append(LINE_END);
        strBuf.append(paramsMap.get(key));
        strBuf.append(LINE_END);
    }
    String paramsString = strBuf.toString();
    out.write(paramsString.getBytes());
    out.flush();
    String fileName = UriUtils.getFileNameByUri(mContext, fileUri);
    String mimeType = UriUtils.getMimeType(mContext, fileUri);
    long fileLength = UriUtils.getFileLength(mContext, fileUri);
    if(!TextUtils.isEmpty(filename)) {
        fileName = filename;
    }
    //add file headers
    out.write(getFileHeaderParamsString(fileKey, fileName, mimeType, fileLength).getBytes());
    //add file body
    String filePath = UriUtils.getFilePath(fileUri);
    InputStream in = null;
    try {
        if (!TextUtils.isEmpty(filePath) && new File(filePath).exists()) {
            in = new FileInputStream(new File(filePath));
        } else {
            in = mContext.getContentResolver().openInputStream(fileUri);
        }
        byte[] tmp = new byte[2048];
        int l;
        long sum = 0;
        while ((l = in.read(tmp)) != -1) {
            out.write(tmp, 0, l);
            sum += l;
            if (callback != null) {
                callback.onProgress(fileLength, sum);
            }
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if (in != null) {
            in.close();
        }
    }
    //add file end
    out.write(getFileEndString().getBytes());
    out.flush();
    HttpResponse response = new HttpResponse();
    //can't get response code here
    response.code = mConn.getResponseCode();
    if(response.code == HttpURLConnection.HTTP_OK) {
        response.contentLength = mConn.getContentLength();
        response.inputStream = mConn.getInputStream();
        response.content = parseStream(response.inputStream);
    }else {
        response.errorStream = mConn.getErrorStream();
        response.content = parseStream(response.errorStream);
    }
    ......

 public static class SSLCustomSocketFactory extends SSLSocketFactory {
    private static final String TAG = "SSLCustomSocketFactory";
    private static final String[] TLS_SUPPORT_VERSION = {"TLSv1.1", "TLSv1.2"};
    private static final String KEY_PASS = "";
    final SSLSocketFactory delegate;
    static SSLContext  sslContext;
    static SSLSocketFactory mSocketFactory;

    public SSLCustomSocketFactory(SSLSocketFactory base) {
        delegate = base;
    }

    @Override
    public String[] getDefaultCipherSuites() {
        return delegate.getDefaultCipherSuites();
    }

    @Override
    public String[] getSupportedCipherSuites() {
        return delegate.getSupportedCipherSuites();
    }

    @Override
    public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
        return patch(delegate.createSocket(s, host, port, autoClose));
    }

    @Override
    public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
        return patch(delegate.createSocket(host, port));
    }

    @Override
    public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException {
        return patch(delegate.createSocket(host, port, localHost, localPort));
    }

    @Override
    public Socket createSocket(InetAddress host, int port) throws IOException {
        return patch(delegate.createSocket(host, port));
    }

    @Override
    public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
        return patch(delegate.createSocket(address, port, localAddress, localPort));
    }

    private Socket patch(Socket s) {
        if(s instanceof SSLSocket) {
            ((SSLSocket) s).setEnabledProtocols(TLS_SUPPORT_VERSION);
        }
        return s;
    }

    public static synchronized SSLSocketFactory getSocketFactory() {
        if(mSocketFactory == null) {
            try {
                CertificateFactory cf = CertificateFactory.getInstance("X.509");
                AssetManager am = context().getAssets();
                String[] certsPaths = am.list("xxx_certs");
                String keyStoreType = KeyStore.getDefaultType();
                KeyStore keyStore = KeyStore.getInstance(keyStoreType);
                keyStore.load(null, null);
                for (int i = 0; i < certsPaths.length; i++) {
                    String certPath = certsPaths[i];
                    InputStream caInput = null;
                    try {
                        caInput = am.open("xxxx_certs/" + certPath);
                        Certificate ca = cf.generateCertificate(caInput);
                        System.out.println("ca=" + ((X509Certificate) ca).getSubjectDN());
                        keyStore.setCertificateEntry("ca" + i, ca);
                    } catch (Exception e) {
                        e.printStackTrace();
                    } finally {
                        if (caInput != null) {
                            caInput.close();
                        }
                    }
                }

                sslContext = SSLContext.getInstance("TLS");
                TrustManagerFactory tmf = TrustManagerFactory.
                        getInstance(TrustManagerFactory.getDefaultAlgorithm());
                tmf.init(keyStore);

                sslContext.init(null, tmf.getTrustManagers(), null);
                mSocketFactory = sslContext.getSocketFactory();
            } catch (Throwable e) {
                e.printStackTrace();
            }
        }
        return mSocketFactory;
    }
}

Here is the nagix return:

<html>

   <head>
      <title>413 Request Entity Too Large</title>
   </head>

   <body>
      <center>
          <h1>413 Request Entity Too Large</h1>
      </center>
      <hr>
      <center>nginx/1.17.5</center>
   </body>

 <html>

How I can get the right exception code and exception message?

neil
  • 1
  • 1
  • I couldn't catch the 413 exception through HttpUrlConnetion's getResponseCode, how can I do? – neil May 30 '20 at 12:00

1 Answers1

0

This is a payload limit determined by the server, there is nothing you can do in your application to accept this payload. You must verify that the format and the amount of data sent is correct. If the server is yours, you must change the limit. Look at this: How to edit nginx.conf to increase file size upload

Wender
  • 991
  • 15
  • 24
  • Thank you for your answer! It's a way to limit the upload file in our company, we do not want to increase file upload size in nginx. The key point is that I could't catch the 413 exception through HttpUrlConnection's getResponseCode. Any other hints? – neil May 30 '20 at 11:47