跪求大神解惑,HttpUrlConnection上传大文件报错,getResponseCode无返回值并报错

黑金白土 2020-05-29 05:22:51
项目中上传文件到服务器,nagix设置了文件最大为10M,如果移动端上传文件超过10M,就上传失败。我用的是android原生网络请求HttpUrlConnection,我希望上传大于10M的文件后,能够得到response code和error message,但是实际上在我获取response code的时候,这句代码就抛出异常了,异常为下面三个(随修改参数,报的异常是三个中的一个)

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

javax.net.ssl.SSLException: Write error: ssl=0x7e67fae408: I/O error during system call, Broken pipe

java.net.SocketException: Connection reset

然后,我通过fiddler抓包,拿到的异常如下:

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

然后问了一下后台,为了负载均衡,特意在nagix上设置10M的限制。
大概原因是,上传超过10M的文件时,nginx检查文件超过设置的最大值,就断开的connection,于是在getResponseCode或者getInputStream的时候,就直接抛异常了。
面对这种情况,我该如何拿到response code?
HttpUrlConnection设置代码如下:

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);
//添加传入的请求头
for (Map.Entry<String, String> item : headers.entrySet()) {
mConn.setRequestProperty(item.getKey(), item.getValue());
}
mConn.connect();
//添加文件
DataOutputStream out = new DataOutputStream(connect.getOutputStream());
//传入的参数
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;
}
//添加文件头
out.write(getFileHeaderParamsString(fileKey, fileName, mimeType, fileLength).getBytes());
//添加文件体
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();
}
}
//添加文件尾
out.write(getFileEndString().getBytes());
out.flush();
HttpResponse response = new HttpResponse();
//上传大文件执行到这里就会抛出异常,但是拿到异常不是所希望的,然后呢,也没有相应码
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);
}
//下面就是对不同code的处理逻辑

//这是SSLSocketFactory类
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");//设计到项目,修改为xxx
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();
}
}
}

//取得SSL的SSLContext实例
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;
}
}


跪求大神解惑,面对这种情况,我该如何处理?
...全文
291 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

80,351

社区成员

发帖
与我相关
我的任务
社区描述
移动平台 Android
androidandroid-studioandroidx 技术论坛(原bbs)
社区管理员
  • Android
  • yechaoa
  • 失落夏天
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧