Android HttpUrlConneion upload a large file cause 413, but getResponseCode can't return and throw another exception

huangapple 未分类评论49阅读模式
英文:

Android HttpUrlConneion upload a large file cause 413, but getResponseCode can't return and throw another exception

问题

在我的应用程序中我使用HttpUrlConnection将文件上传到服务器当我尝试上传一个大文件时nginx返回一个413异常代码但是HttpUrlConnection的getResponseCode方法无法捕获异常我得到了另一个异常消息
以下是异常消息

    错误 asyncExecute: 写入错误ssl=0x7ec7b80008系统调用期间的I/O错误连接被对等方重置

以下是我的代码

    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

<details>
<summary>英文:</summary>

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&#39;s getResponseCode can&#39;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, &quot;http&quot;)) {
            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(&quot;POST&quot;);
        mConn.setDoOutput(true);
        mConn.setDoInput(true);
        mConn.setUseCaches(false);
        mConn.setConnectTimeout(30000);
        mConn.setReadTimeout(30000);
        mConn.setRequestProperty(&quot;User-agent&quot;, &quot;xxxx&quot;);//xxxx涉及到项目中信息不展示
        mConn.setRequestProperty(&quot;Connection&quot;, &quot;Keep-Alive&quot;);
        mConn.setRequestProperty(&quot;Charset&quot;, &quot;UTF-8&quot;);
        mConn.setRequestProperty(&quot;Content-Type&quot;, &quot;multipart/form-data; boundary=&quot; + BOUNDARY);
        mConn.setRequestProperty(&quot;Expect&quot;, &quot;100-Continue&quot;);
        mConn.setChunkedStreamingMode(0);
        //request headers
        for (Map.Entry&lt;String, String&gt; 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(&quot;Content-Disposition: form-data; name=\&quot;&quot; + key + &quot;\&quot;&quot;);
            strBuf.append(LINE_END);
 
            strBuf.append(&quot;Content-Type: &quot; + &quot;text/plain&quot; );
            strBuf.append(LINE_END);
            strBuf.append(&quot;Content-Length: &quot;+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) &amp;&amp; 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&#39;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 = &quot;SSLCustomSocketFactory&quot;;
        private static final String[] TLS_SUPPORT_VERSION = {&quot;TLSv1.1&quot;, &quot;TLSv1.2&quot;};
        private static final String KEY_PASS = &quot;&quot;;
        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(&quot;X.509&quot;);
                    AssetManager am = context().getAssets();
                    String[] certsPaths = am.list(&quot;xxx_certs&quot;);
                    String keyStoreType = KeyStore.getDefaultType();
                    KeyStore keyStore = KeyStore.getInstance(keyStoreType);
                    keyStore.load(null, null);
                    for (int i = 0; i &lt; certsPaths.length; i++) {
                        String certPath = certsPaths[i];
                        InputStream caInput = null;
                        try {
                            caInput = am.open(&quot;xxxx_certs/&quot; + certPath);
                            Certificate ca = cf.generateCertificate(caInput);
                            System.out.println(&quot;ca=&quot; + ((X509Certificate) ca).getSubjectDN());
                            keyStore.setCertificateEntry(&quot;ca&quot; + i, ca);
                        } catch (Exception e) {
                            e.printStackTrace();
                        } finally {
                            if (caInput != null) {
                                caInput.close();
                            }
                        }
                    }
 
                    sslContext = SSLContext.getInstance(&quot;TLS&quot;);
                    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:

    &lt;html&gt;
 
       &lt;head&gt;
          &lt;title&gt;413 Request Entity Too Large&lt;/title&gt;
       &lt;/head&gt;
 
       &lt;body&gt;
          &lt;center&gt;
              &lt;h1&gt;413 Request Entity Too Large&lt;/h1&gt;
          &lt;/center&gt;
          &lt;hr&gt;
          &lt;center&gt;nginx/1.17.5&lt;/center&gt;
       &lt;/body&gt;
 
     &lt;html&gt;

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

</details>


# 答案1
**得分**: 0

这是服务器确定的有效载荷限制您的应用程序无法对此有效载荷进行任何操作以接受它您必须验证发送的格式和数据量是否正确
如果服务器是您自己的您必须更改此限制请参考这个链接https://stackoverflow.com/questions/26717013/how-to-edit-nginx-conf-to-increase-file-size-upload

<details>
<summary>英文:</summary>

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: https://stackoverflow.com/questions/26717013/how-to-edit-nginx-conf-to-increase-file-size-upload

</details>



huangapple
  • 本文由 发表于 2020年5月29日 18:20:16
  • 转载请务必保留本文链接:https://java.coder-hub.com/62083740.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定