Android HttpUrlConneion загружает большой файл, причина 413, но getResponseCode не может вернуть и вызвать другое исключение - PullRequest
0 голосов
/ 29 мая 2020

В моем приложении я использую HttpUrlConnection для загрузки файла на сервер, когда я хочу загрузить большой файл, nginx дает мне код исключения 413, но getResponseCode HttpUrlConnection не может поймать исключение, я получил еще одно сообщение об исключении. Вот сообщение об исключении:

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>

Как я могу получить право код исключения и сообщение об исключении?

1 Ответ

0 голосов
/ 29 мая 2020

Это предел полезной нагрузки, определяемый сервером, вы ничего не можете сделать в своем приложении, чтобы принять эту полезную нагрузку. Вы должны убедиться, что формат и объем отправленных данных верны. Если сервер ваш, необходимо изменить лимит. Посмотрите на это: Как отредактировать nginx .conf для увеличения размера загружаемого файла

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...