java - Android HttpUrlConneion上传大文件导致413,但getResponseCode无法返回并抛出另一个异常

标签 java android

在我的应用程序中,我使用 HttpUrlConnection 将文件上传到服务器,当我想上传大文件时,nginx 给我一个 413 异常代码,但是 HttpUrlConnection 的 getResponseCode 无法捕获该异常,我收到了另一条异常消息。 这是异常消息:

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

这是我的代码:

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

这是 nagix 返回:

<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 to edit nginx.conf to increase file size upload

关于java - Android HttpUrlConneion上传大文件导致413,但getResponseCode无法返回并抛出另一个异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62083740/

相关文章:

android - 从网络加载 ItemizedOverlays 标记

java - 更改操作栏和其他元素的颜色

android - System.out.print with//打印代码 Blue。这是什么意思?

android - UiAutomator 2.0 相当于 scrollIntoView

java - 如何将 Kotlin 文件添加到旧的 android java 项目?

Java Triple DES 算法 填充模式

java - 本地 Google Appengine 上的 JUnit 测试中的电子邮件正文为空

android OAuth-2.0 google登录使用webview获取用户信息

java - 我如何在 JSP 页面中获取任何字符串值

java - 获取带有玻璃的 GWT PopupPanel 淡入淡出