从 Asp.net 客户端上传大文件到 JBoss 问题
Posted
技术标签:
【中文标题】从 Asp.net 客户端上传大文件到 JBoss 问题【英文标题】:Upload large file to JBoss Issue from Asp.net Client 【发布时间】:2012-09-25 09:55:42 【问题描述】:所有,我有一个使用 apache-common-fileupload 组件的 JBoss 应用程序,我测试过它可以从在 post 方法中使用 HttpWebRequest 的 asp.net 客户端上传大文件。但是在多次成功上传后。它在JBoss控制台中失败并出现以下异常。请帮忙检查一下。谢谢。
org.apache.commons.fileupload.FileUploadBase$IOFileUploadException: Processing of multipart/form-data request failed. Stream ended unexpectedly
at org.apache.commons.fileupload.FileUploadBase.parseRequest(FileUploadBase.java:359)
at com.accela.deploy.servlet.RequestHandler.getUploadFileFromRequest(RequestHandler.java:86)
at com.accela.deploy.servlet.DeployServlet.doPost(DeployServlet.java:122)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:710)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at com.accela.commom.filter.AuthFilter.doFilter(AuthFilter.java:99)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:182)
at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:84)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.jboss.web.tomcat.service.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:157)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:615)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
at org.apache.coyote.http11.Http11AprProcessor.process(Http11AprProcessor.java:877)
at org.apache.coyote.http11.Http11AprProtocol$Http11ConnectionHandler.process(Http11AprProtocol.java:594)
at org.apache.tomcat.util.net.AprEndpoint$Worker.run(AprEndpoint.java:1733)
at java.lang.Thread.run(Thread.java:722)
这里是 server.xml 内容。请检查一下。
<!--APR library loader. Documentation at /docs/apr.html -->
<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
<!--Initialize Jasper prior to webapps are loaded. Documentation at /docs/jasper-howto.html -->
<Listener className="org.apache.catalina.core.JasperListener" />
<Service name="jboss.web">
<!-- A HTTP/1.1 Connector (Http11Protocol Http11NioProtocol Http11AprProtocol)-->
<Connector protocol="org.apache.coyote.http11.Http11AprProtocol"
address="$jboss.bind.address" port="$av.http.port"
scheme="http" secure="false"
URIEncoding="UTF-8"
redirectPort="$av.https.port"
maxHttpHeaderSize="8192"
maxThreads="$av.http.maxThreads:500"
acceptCount="$av.http.acceptCount:200"
enableLookups="false"
disableUploadTimeout="true"
/>
<!-- Java SSL Coyote HTTP/1.1 Connector using Apache Portable Runtime (APR) -->
<Connector protocol="org.apache.coyote.http11.Http11AprProtocol"
address="$jboss.bind.address" port="$av.https.port"
scheme="https" secure="true"
URIEncoding="UTF-8"
maxHttpHeaderSize="8192"
maxThreads="$av.https.maxThreads:500"
acceptCount="$av.https.acceptCount:200"
enableLookups="false"
disableUploadTimeout="true"
SSLEnabled="true"
SSLVerifyClient="none"
SSLProtocol="all"
SSLCipherSuite="!aNULL:!ADH:!eNULL:!LOW:!EXP:!SSLv2:RC4+RSA:+HIGH:+MEDIUM:ALL"
SSLCertificateFile="$jboss.server.home.dir/conf/certs/$av.host.crt"
SSLCertificateKeyFile="$jboss.server.home.dir/conf/certs/$av.host.key"
/>
<Engine name="jboss.web" defaultHost="localhost">
<Realm className="org.jboss.web.tomcat.security.JBossSecurityMgrRealm"
certificatePrincipal="org.jboss.security.auth.certs.SubjectDNMapping"
allRolesMode="authOnly"
/>
<Host name="localhost"
autoDeploy="false" deployOnStartup="false" deployXML="false"
configClass="org.jboss.web.tomcat.security.config.JBossContextConfig">
<Valve className="org.apache.catalina.valves.AccessLogValve"
prefix="av.web.$jboss.bind.address.access."
suffix=".log"
pattern="%a %t %T "%r" %s %b %u %S %p"
directory="$jboss.server.log.dir"
resolveHosts="false" />
<Valve className="org.jboss.web.tomcat.service.sso.ClusteredSingleSignOn" />
-->
<!-- Check for unclosed connections and transaction terminated checks
in servlets/jsps.
Important: The dependency on the CachedConnectionManager
in META-INF/jboss-service.xml must be uncommented, too
-->
<Valve className="org.jboss.web.tomcat.service.jca.CachedConnectionValve"
cachedConnectionManagerObjectName="jboss.jca:service=CachedConnectionManager"
transactionManagerObjectName="jboss:service=TransactionManager" />
</Host>
</Engine>
</Service>
编辑并添加了 Asp.net 客户端代码。
public static bool SendSingleChunk(string sRequestUrl,int iOffset, int iChunkSize)
string sPackFullUriName = "d:\\2GB.zip";
string boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x");
byte[] boundarybytes = System.Text.Encoding.ASCII.GetBytes("--" + boundary + "\r\n");
string headerTemplate = "Content-Disposition: form-data; name=\"0\"; filename=\"1\"\r\n"
+ "Content-Type: application/octet-stream\r\n\r\n";
sFName = Path.GetFileName(sPackFullUriName);
string header = string.Format(headerTemplate, sFName, sPackFullUriName);
byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(header);
byte[] endBoundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n");
Stream requestStream = null;
HttpWebRequest request = null;
byte[] bData = null;
try
bData = StorageHelper.ChunkReadFromDiskFile(sPackFullUriName, iOffset, iChunkSize);
Log.Write("This is the " + iChunkindex + " times to send chunk, size is " + bData.Length.ToString());
long lContentLen = bData.Length + boundarybytes.Length + headerbytes.Length + endBoundarybytes.Length;
string sContentType = "multipart/form-data; boundary=" + boundary;
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(sRequestUrl);
request.Method = WebRequestMethods.Http.Post;
request.KeepAlive = false;
request.Timeout = 300 * 60 * 1000; //300 mins;
request.ContentLength = lContentLen;
request.AllowAutoRedirect = false;
request.ContentType = sContentType;
using (requestStream = request.GetRequestStream())
requestStream.Write(boundarybytes, 0, boundarybytes.Length);
requestStream.Write(headerbytes, 0, headerbytes.Length);
if (bData != null)
requestStream.Write(bData, 0, bData.Length);
else
return false;
//requestStream.Write(formitembytes, 0, formitembytes.Length);
requestStream.Write(endBoundarybytes, 0, endBoundarybytes.Length);
requestStream.Flush();
requestStream.Close();
string returnedContent = string.Empty;
using (var response = (HttpWebResponse)request.GetResponse())
using (var responseStream = response.GetResponseStream())
using (StreamReader reader = new StreamReader(responseStream))
returnedContent = reader.ReadToEnd();
reader.Close();
response.Close();
if (DeployConfig.ResultSucceed.Equals("OK", StringComparison.InvariantCultureIgnoreCase))
return true;
else
return false;
catch (Exception ex)
return false;
finally
bData = null;
我的想法:
我相信Stream ended unexpectedly
异常的根本原因是我发布到服务器的流的长度不完全等于我在 HttpWebRequest.ContentLength 中指定的长度。
我的问题:
1.如果HttpWebRequest.ContentLength的长度大于或小于我发送到服务器的实际大小怎么办?
2.如果我在发帖失败后继续执行
SendSingleChunk
怎么办?似乎服务器将这两个请求流识别为同一个。
【问题讨论】:
你是如何上传文件的?什么浏览器和版本?查看相关线程***.com/questions/646189/…。 好问题,我正在使用 asp.net HttpWebRequest post 方法模拟以 html 形式发布文件。 >string boundary = "----------------------------" + DateTime.Now.Ticks.ToString("x");string sContentType = "multipart/form-data; boundary=" + boundary;
我不发布 .net 代码的原因,因为我认为这对于解决问题并不重要。但还有什么你想知道的请告诉我。谢谢。
什么类型的应用程序?可以发一下代码吗?
您是否消除了传输/网络层问题的可能性?我建议在上传时进行连续 ping。任何 ping 中断或数据包返回时间过长都表明存在网络问题。
【参考方案1】:
错误信息说:
.. Stream ended unexpectedly
这很可能是因为asp.net
客户端应用程序在几次成功上传后意外关闭了套接字,或者可能存在连接问题。有关此错误的可能原因的完整讨论,请参阅以下主题。
Why did I get "FileUploadException: Stream ended unexpectedly" with Apache Commons FileUpload?
【讨论】:
为什么套接字意外关闭?如果存在连接问题,我该如何识别? 可能是asn.net
客户端问题,也可能是其他问题。你有没有和另一个客户测试过?例如浏览器?【参考方案2】:
所有,对于上传大文件的问题,这里有一些我们应该关心的提示。
无论您使用什么网络服务器,实际上是在从某个客户端向其上传文件的过程中,接收到数据后要做的第一件事就是将数据持久化到某个临时目录。因此,首先要确保服务器中的应用程序有足够的权限将数据写入磁盘。
其次。如果我们像我一样使用底层 html 协议上传文件。
我们应该仔细检查协议,确保每个步骤都遵循协议。这是它的doc。
我要说的最后一件事是,如果您出于某种目的将 asp.net 用作 Web 客户端,则必须仔细检查 HttpWebRequest
的这些属性的用途。谢谢。
request.KeepAlive = false;
request.Timeout = 300 * 60 * 1000; //300 mins;
request.ContentLength = lContentLen;
request.AllowAutoRedirect = false;
【讨论】:
以上是关于从 Asp.net 客户端上传大文件到 JBoss 问题的主要内容,如果未能解决你的问题,请参考以下文章