我正在尝试在tomcat服务器上传视频,但在上传一个视频后我得到了以下错误:
错误日志:
org.apache.jasper.JasperException: An exception occurred processing JSP page /SaveVideos.jsp at line 34
31: pos = file.indexOf("\n", pos) + 1;
32: int boundaryLocation = file.indexOf(boundary, pos) - 4;
33: int startPos = ((file.substring(0, pos)).getBytes()).length;
34: int endPos = ((file.substring(0, boundaryLocation)).getBytes()).length;
35:
36: // String pathToFile = this.getServletContext().getRealPath(request.getPathInfo());
37: File ff = new File(this.getServletContext().getRealPath("/")+"videos/"+ saveFile);
Stacktrace:
org.apache.jasper.servlet.JspServletWrapper.handleJspException(JspServletWrapper.java:524)
org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:417)
org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:320)
org.apache.jasper.servlet.JspServlet.service(JspServlet.java:266)
javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
root cause
javax.servlet.ServletException: java.lang.OutOfMemoryError: Java heap space
org.apache.jasper.runtime.PageContextImpl.doHandlePageException(PageContextImpl.java:850)
org.apache.jasper.runtime.PageContextImpl.handlePageException(PageContextImpl.java:779)
org.apache.jsp.SaveVideos_jsp._jspService(SaveVideos_jsp.java:138)
org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:393)
org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:320)
org.apache.jasper.servlet.JspServlet.service(JspServlet.java:266)
javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
root cause
java.lang.OutOfMemoryError: Java heap space
java.lang.StringCoding$StringEncoder.encode(StringCoding.java:232)
java.lang.StringCoding.encode(StringCoding.java:272)
java.lang.StringCoding.encode(StringCoding.java:284)
java.lang.String.getBytes(String.java:987)
org.apache.jsp.SaveVideos_jsp._jspService(SaveVideos_jsp.java:90)
org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:393)
org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:320)
org.apache.jasper.servlet.JspServlet.service(JspServlet.java:266)
javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
SaveVideo.jsp:
<%@ page import="java.io.*,java.sql.*,java.util.zip.*"%>
<%@ page import="jdbc.DBConnection"%>
<%
String saveFile = "";
String contentType = request.getContentType();
if ((contentType != null)
&& (contentType.indexOf("multipart/form-data") >= 0)) {
DataInputStream in = new DataInputStream(request
.getInputStream());
int formDataLength = request.getContentLength();
byte dataBytes[] = new byte[formDataLength];
int byteRead = 0;
int totalBytesRead = 0;
while (totalBytesRead < formDataLength) {
byteRead = in.read(dataBytes, totalBytesRead,
formDataLength);
totalBytesRead += byteRead;
}
String file = new String(dataBytes);
saveFile = file.substring(file.indexOf("filename=\"") + 10);
saveFile = saveFile.substring(0, saveFile.indexOf("\n"));
saveFile = saveFile.substring(saveFile.lastIndexOf("\\") + 1,
saveFile.indexOf("\""));
int lastIndex = contentType.lastIndexOf("=");
String boundary = contentType.substring(lastIndex + 1,
contentType.length());
int pos;
pos = file.indexOf("filename=\"");
pos = file.indexOf("\n", pos) + 1;
pos = file.indexOf("\n", pos) + 1;
pos = file.indexOf("\n", pos) + 1;
int boundaryLocation = file.indexOf(boundary, pos) - 4;
int startPos = ((file.substring(0, pos)).getBytes()).length;
int endPos = ((file.substring(0, boundaryLocation)).getBytes()).length;
// String pathToFile = this.getServletContext().getRealPath(request.getPathInfo());
File ff = new File(this.getServletContext().getRealPath("/")+"videos/"+ saveFile);
FileOutputStream fileOut = new FileOutputStream(ff);
fileOut.write(dataBytes, startPos, (endPos - startPos));
fileOut.flush();
fileOut.close();
%><br>
<table border="2">
<tr>
<td><b>You have successfully upload the file:</b> <%
response.sendRedirect("HomePage.jsp");
%>
</td>
</tr>
</table>
<%
DBConnection db_con = new DBConnection();
PreparedStatement psmnt = null;
try {
Connection con = db_con.getConnection();
psmnt = con.prepareStatement("insert into video_tbl(Video_name ) values(?)");
psmnt.setString(1,saveFile);
int s = psmnt.executeUpdate();
if (s > 0) {
System.out.println("Uploaded successfully !");
} else {
System.out.println("Error!");
}
} catch (Exception e) {
e.printStackTrace();
}
}
%>
构造
VM Arguments :
-Xms1024m -Xmx1024m
答案 0 :(得分:6)
您的代码存在两个相关问题:
您正在缓存内存中的整个上传文档(视频)。这会占用大量内存,并且最有可能是您OOME的原因。
与上一个相关,如果fileContent超过2^32 - 1
字节(即超过2Gb),您的代码将失败,因为内容长度不适合int
,并且您不能分配超过2^32 - 1
个元素的数组。
你需要做的是这样的事情:
InputStream
换成BufferedInputStream
而不是DataInputStream
。read()
一次一个字节地读取并累积表单数据“信封”数据,直到您到达换行符。然后将每一行转换为字符串以进行解析。BufferedOutputStream
将(非边界)数据字节写入输出文件。更好的是,如果你看起来你应该能够找到处理多部分的现有组件。
您还遇到了一个问题,即您在JSP中嵌入了重要的“业务逻辑”作为“scriptlet”代码。这是糟糕的做法。您应该在Servlet中执行业务逻辑(数据库查询和更新,文件上载等),并使用JSP来呈现输出。
答案 1 :(得分:3)
您可以重写代码,使其直接从输入流流式传输到文件。这只需要一个小缓冲区。
答案 2 :(得分:0)
您在内存中创建两次视频: 1. byte dataBytes [] = new byte [formDataLength]; 2. String file = new String(dataBytes);
您可能想要更改...