1

我正在尝试在 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)

保存视频.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
4

3 回答 3

6

您的代码有两个相关问题:

  1. 您正在内存中缓冲整个上传的文档(视频)。这会占用大量内存,并且最有可能导致您的 OOME。

  2. 与前面相关,如果 fileContent 超过2^32 - 1字节(即超过 2Gb),您的代码将失败,因为内容长度不适合 an int,并且您不能分配包含多个2^32 - 1元素的数组。

你需要做的是这样的:

  • 将 a包裹InputStreamBufferedInputStreamnot aDataInputStream中。
  • 一次一个字节地读取并累积表单数据“信封”数据,read()直到到达换行符为止。然后将每一行变成一个字符串来进行解析。
  • 到达文件内容的开头后,一次读取一个字节以查找边界序列,并通过BufferedOutputStream.

更好的是,如果您查看,您应该能够找到用于处理多部分的现有组件。


您还遇到了一个问题,即在您的 JSP 中嵌入了重要的“业务逻辑”作为“scriptlet”代码。这是不好的做法。您应该在 Servlet 中执行业务逻辑(数据库查询和更新、文件上传等),并且只使用 JSP 来呈现输出。

于 2013-05-31T10:29:06.487 回答
3

您可以重写代码,使其直接从输入流流式传输到文件。这只需要一个小的缓冲区。

于 2013-05-31T09:55:40.143 回答
0

您在内存中创建了两次视频: 1. byte dataBytes[] = new byte[formDataLength]; 2. 字符串文件 = new String(dataBytes);

你可能想改变它...

于 2013-05-31T09:47:13.277 回答