如何使用 JSP/Servlet 将文件上传到服务器?

How can I upload files to a server using JSP/Servlet?

提问人:Thang Pham 提问时间:3/11/2010 最后编辑:BalusCThang Pham 更新时间:10/6/2023 访问量:648650

问:

如何使用 JSP/Servlet 将文件上传到服务器?

我试过了这个:

<form action="upload" method="post">
    <input type="text" name="description" />
    <input type="file" name="file" />
    <input type="submit" />
</form>

但是,我只得到文件名,而不是文件内容。当我添加 时,然后返回 .enctype="multipart/form-data"<form>request.getParameter()null

在研究过程中,我偶然发现了 Apache Common FileUpload。我试过了这个:

FileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
List items = upload.parseRequest(request); // This line is where it died.

不幸的是,servlet 在没有明确消息和原因的情况下抛出异常。下面是堆栈跟踪:

SEVERE: Servlet.service() for servlet UploadServlet threw exception
javax.servlet.ServletException: Servlet execution threw an exception
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:313)
    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.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:852)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
    at java.lang.Thread.run(Thread.java:637)
jsp servlet 文件上传

评论

0赞 Adam Gerard 1/15/2019
也许这篇文章会有所帮助:baeldung.com/upload-file-servlet
1赞 BalusC 2/24/2021
@Adam:他们复制了我的答案,并在上面添加了广告侦探,试图用它来赚钱。是的,很棒的文章..
1赞 Adam Gerard 3/29/2021
不,实际上什么都没有被复制。我写了那篇文章的初稿和补充代码。核心参考文档可以在这里找到:commons.apache.org/proper/commons-fileupload/using.html(并在文章中链接和引用)。示例部分转载自核心参考文档(这是参考文档的要点 - 即作为参考点),但不是全部(请注意,参考文档没有详细说明)。谢谢!
0赞 ricky 7/27/2021
检查此 sandny.com/2017/05/18/servlet-file-upload

答:

1257赞 BalusC 3/11/2010 #1

介绍

要浏览和选择要上传的文件,您需要在表单中有一个 HTML 字段。如 HTML 规范中所述,您必须使用该方法,并且表单的属性必须设置为 。<input type="file">POSTenctype"multipart/form-data"

<form action="upload" method="post" enctype="multipart/form-data">
    <input type="text" name="description" />
    <input type="file" name="file" />
    <input type="submit" />
</form>

提交此类表单后,二进制多部分表单数据将在请求正文中以与未设置时不同的格式提供。enctype

在 Servlet 3.0(2009 年 12 月)之前,Servlet API 本身不支持 。它仅支持默认的表单 enctype。使用多部分表单数据时,和 consorts 都将返回。这就是著名的 Apache Commons FileUpload 出现的地方。multipart/form-dataapplication/x-www-form-urlencodedrequest.getParameter()null

不要手动解析它!

理论上,您可以根据 ServletRequest#getInputStream() 自行解析请求体。然而,这是一项精确而乏味的工作,需要对RFC2388有精确的了解。你不应该尝试自己做这件事,或者复制粘贴一些在互联网上其他地方找到的自制的无库代码。许多在线资源在这方面都失败了,例如 roseindia.net。另请参阅上传 pdf 文件。你更应该使用一个真正的库,它被数百万用户使用(并隐式测试)多年。这样的库已经证明了它的健壮性。

如果您已经在 Servlet 3.0 或更高版本上,请使用本机 API

如果您至少使用 Servlet 3.0(Tomcat 7、Jetty 9、JBoss AS 6、GlassFish 3 等,它们自 2010 年以来就已经存在了),那么您可以只使用提供的标准 API HttpServletRequest#getPart() 来收集单个多部分表单数据项(大多数 Servlet 3.0 实现实际上都使用 Apache Commons FileUpload!此外,普通表单字段也可以通过通常的方式使用。getParameter()

首先用 @MultipartConfig 注释你的 servlet,以便让它识别和支持请求,从而开始工作:multipart/form-datagetPart()

@WebServlet("/upload")
@MultipartConfig
public class UploadServlet extends HttpServlet {
    // ...
}

然后,按如下方式实现其:doPost()

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    String description = request.getParameter("description"); // Retrieves <input type="text" name="description">
    Part filePart = request.getPart("file"); // Retrieves <input type="file" name="file">
    String fileName = Paths.get(filePart.getSubmittedFileName()).getFileName().toString(); // MSIE fix.
    InputStream fileContent = filePart.getInputStream();
    // ... (do your job here)
}

请注意 .这是关于获取文件名的 MSIE 修复程序。此浏览器错误地沿名称发送完整的文件路径,而不仅仅是文件名。Path#getFileName()

如果您想通过以下任一方式上传多个文件 ,multiple="true"

<input type="file" name="files" multiple="true" />

或具有多个输入的老式方式,

<input type="file" name="files" />
<input type="file" name="files" />
<input type="file" name="files" />
...

然后您可以按如下方式收集它们(不幸的是没有这样的方法):request.getParts("files")

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    // ...
    List<Part> fileParts = request.getParts().stream().filter(part -> "files".equals(part.getName()) && part.getSize() > 0).collect(Collectors.toList()); // Retrieves <input type="file" name="files" multiple="true">

    for (Part filePart : fileParts) {
        String fileName = Paths.get(filePart.getSubmittedFileName()).getFileName().toString(); // MSIE fix.
        InputStream fileContent = filePart.getInputStream();
        // ... (do your job here)
    }
}

当您尚未使用 Servlet 3.1 时,请手动获取提交的文件名

请注意,Part#getSubmittedFileName() 是在 Servlet 3.1 中引入的(Tomcat 8、Jetty 9、WildFly 8、GlassFish 4 等,它们自 2013 年以来就已经存在了)。如果您还没有使用 Servlet 3.1(真的吗?),那么您需要一个额外的实用程序方法来获取提交的文件名。

private static String getSubmittedFileName(Part part) {
    for (String cd : part.getHeader("content-disposition").split(";")) {
        if (cd.trim().startsWith("filename")) {
            String fileName = cd.substring(cd.indexOf('=') + 1).trim().replace("\"", "");
            return fileName.substring(fileName.lastIndexOf('/') + 1).substring(fileName.lastIndexOf('\\') + 1); // MSIE fix.
        }
    }
    return null;
}
String fileName = getSubmittedFileName(filePart);

请注意有关获取文件名的 MSIE 修复。此浏览器错误地沿名称发送完整的文件路径,而不仅仅是文件名。

如果您还没有使用 Servlet 3.0,请使用 Apache Commons FileUpload

如果您还没有使用 Servlet 3.0(现在是不是该升级了?它已经发布了十多年!),通常的做法是使用 Apache Commons FileUpload 来解析多个表单数据请求。它有一个优秀的用户指南常见问题解答(仔细阅读两者)。还有 O'Reilly (“cos”) ,但它有一些(小)错误,并且多年来不再积极维护。我不建议使用它。Apache Commons FileUpload 仍在积极维护中,目前非常成熟。MultipartRequest

为了使用 Apache Commons FileUpload,您的 Web 应用程序中至少需要包含以下文件:/WEB-INF/lib

您的初始尝试失败很可能是因为您忘记了公共 IO。

下面是一个启动示例,说明使用 Apache Commons FileUpload 时的样子:doPost()UploadServlet

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    try {
        List<FileItem> items = new ServletFileUpload(new DiskFileItemFactory()).parseRequest(request);
        for (FileItem item : items) {
            if (item.isFormField()) {
                // Process regular form field (input type="text|radio|checkbox|etc", select, etc).
                String fieldName = item.getFieldName();
                String fieldValue = item.getString();
                // ... (do your job here)
            } else {
                // Process form file field (input type="file").
                String fieldName = item.getFieldName();
                String fileName = FilenameUtils.getName(item.getName());
                InputStream fileContent = item.getInputStream();
                // ... (do your job here)
            }
        }
    } catch (FileUploadException e) {
        throw new ServletException("Cannot parse multipart request.", e);
    }

    // ...
}

非常重要的一点是,您不要事先在同一请求上调用 、 、 、 、 等。否则,servlet 容器将读取并解析请求正文,因此 Apache Commons FileUpload 将得到一个空的请求正文。参见 a.o. ServletFileUpload#parseRequest(request) 返回一个空列表getParameter()getParameterMap()getParameterValues()getInputStream()getReader()

请注意 .这是关于获取文件名的 MSIE 修复程序。此浏览器错误地沿名称发送完整的文件路径,而不仅仅是文件名。FilenameUtils#getName()

或者,您也可以将所有这些包装在自动解析所有内容中,并将内容放回请求的参数映射中,以便您可以继续使用通常的方式并通过 检索上传的文件。您可以在这篇博客文章中找到一个示例Filterrequest.getParameter()request.getAttribute()

GlassFish3 仍然返回错误的解决方法getParameter()null

请注意,早于 3.1.2 的 Glassfish 版本存在一个错误,其中 still 返回 .如果以这样的容器为目标,但无法升级它,则需要借助以下实用程序方法从中提取值:getParameter()nullgetPart()

private static String getValue(Part part) throws IOException {
    BufferedReader reader = new BufferedReader(new InputStreamReader(part.getInputStream(), "UTF-8"));
    StringBuilder value = new StringBuilder();
    char[] buffer = new char[1024];
    for (int length = 0; (length = reader.read(buffer)) > 0;) {
        value.append(buffer, 0, length);
    }
    return value.toString();
}
String description = getValue(request.getPart("description")); // Retrieves <input type="text" name="description">
    

保存上传的文件(不要使用,也不要使用!getRealPath()part.write()

有关将获取的变量(如上述代码片段所示的变量)正确保存到磁盘或数据库的详细信息,请参阅以下答案:InputStreamfileContent

提供上传的文件

有关将保存的文件从磁盘或数据库正确提供回客户端的详细信息,请前往以下答案:

Ajaxifying 表单

前往以下答案:如何使用 Ajax(和 jQuery)上传。请注意,不需要为此更改用于收集表单数据的 servlet 代码!只有您的响应方式可能会改变,但这是相当微不足道的(即,只需打印一些 JSON 或 XML 甚至纯文本,而不是转发到 JSP,具体取决于负责 Ajax 调用的脚本所期望的内容)。

评论

0赞 Kagami Sascha Rosylight 11/6/2016
啊对不起,我看到了,很困惑x_xrequest.getParts("file")
0赞 theyuv 11/20/2016
在 Servlet 3.0 中,如果违反了条件(例如:),调用将返回 null。这是故意的吗?如果我在调用(并检查)之前得到一些常规(文本)参数怎么办?这会导致在我有机会检查 .MultipartConfigmaxFileSizerequest.getParameter()getPartIllegalStateExceptionNullPointerExceptionIllegalStateException
0赞 Rapster 8/1/2017
@BalusC我创建了与此相关的帖子,您知道如何从文件 API webKitDirectory 中检索额外信息吗?更多细节在这里 stackoverflow.com/questions/45419598/...
1赞 raviraja 9/24/2018
是的,如果有人尝试在 Tomcat 7 中使用 3.0 部分中的代码,他们可能会遇到与我类似的问题String fileName = Paths.get(filePart.getSubmittedFileName()).getFileName().toString(); // MSIE fix.
2赞 BalusC 4/1/2021
@aaa:当您使用和/或原因不明将字节转换为字符时,可能会发生这种情况。不要那样做。在读取和写入上传的文件期间,在所有地方使用 /,而无需将字节按摩成字符。PDF 文件不是基于字符的文本文件。它是一个二进制文件。ReaderWriterInputStreamOutputStream
11赞 Pranav 5/17/2012 #2

您需要将文件包含在目录中,或者如果您正在使用任何编辑器(如 NetBeans),则需要转到项目属性并添加 JAR 文件即可完成。common-io.1.4.jarlib

要获取该文件,只需谷歌一下,或者直接访问 Apache Tomcat 网站,在那里您可以选择免费下载此文件。但请记住一件事:如果您是 Windows 用户,请下载二进制 ZIP 文件。common.io.jar

评论

0赞 Malwinder Singh 10/9/2014
找不到,但是 .你的意思是 ?.jar.zip.zip
9赞 Nagappa L M 1/8/2013 #3

我为每个 HTML 表单使用一个通用的 Servlet,无论它是否有附件。

此 Servlet 返回一个键是 JSP 名称、参数和值是用户输入,并将所有附件保存在一个固定目录中,然后重命名您选择的目录。这里 Connections 是我们的自定义接口,有一个连接对象。TreeMap

public class ServletCommonfunctions extends HttpServlet implements
        Connections {

    private static final long serialVersionUID = 1L;

    public ServletCommonfunctions() {}

    protected void doPost(HttpServletRequest request,
                          HttpServletResponse response) throws ServletException,
                          IOException {}

    public SortedMap<String, String> savefilesindirectory(
            HttpServletRequest request, HttpServletResponse response)
            throws IOException {

        // Map<String, String> key_values = Collections.synchronizedMap(new
        // TreeMap<String, String>());
        SortedMap<String, String> key_values = new TreeMap<String, String>();
        String dist = null, fact = null;
        PrintWriter out = response.getWriter();
        File file;
        String filePath = "E:\\FSPATH1\\2KL06CS048\\";
        System.out.println("Directory Created   ????????????"
            + new File(filePath).mkdir());
        int maxFileSize = 5000 * 1024;
        int maxMemSize = 5000 * 1024;

        // Verify the content type
        String contentType = request.getContentType();
        if ((contentType.indexOf("multipart/form-data") >= 0)) {
            DiskFileItemFactory factory = new DiskFileItemFactory();
            // Maximum size that will be stored in memory
            factory.setSizeThreshold(maxMemSize);
            // Location to save data that is larger than maxMemSize.
            factory.setRepository(new File(filePath));
            // Create a new file upload handler
            ServletFileUpload upload = new ServletFileUpload(factory);
            // maximum file size to be uploaded.
            upload.setSizeMax(maxFileSize);
            try {
                // Parse the request to get file items.
                @SuppressWarnings("unchecked")
                List<FileItem> fileItems = upload.parseRequest(request);
                // Process the uploaded file items
                Iterator<FileItem> i = fileItems.iterator();
                while (i.hasNext()) {
                    FileItem fi = (FileItem) i.next();
                    if (!fi.isFormField()) {
                        // Get the uploaded file parameters
                        String fileName = fi.getName();
                        // Write the file
                        if (fileName.lastIndexOf("\\") >= 0) {
                            file = new File(filePath
                                + fileName.substring(fileName
                                        .lastIndexOf("\\")));
                        } else {
                            file = new File(filePath
                                + fileName.substring(fileName
                                        .lastIndexOf("\\") + 1));
                        }
                        fi.write(file);
                    } else {
                        key_values.put(fi.getFieldName(), fi.getString());
                    }
                }
            } catch (Exception ex) {
                System.out.println(ex);
            }
        }
        return key_values;
    }
}

评论

0赞 AmanS 10/20/2013
@buhake sindi 嘿,如果我使用的是实时服务器,或者我通过将文件上传到服务器来直播我的项目,文件路径应该是什么
2赞 Nagappa L M 10/20/2013
live server中的任何目录。如果您编写代码在servlet中创建目录,则将在live srver中创建目录
6赞 Geoffrey Malafsky 9/10/2013 #4

如果将 Geronimo 与其嵌入式 Tomcat 一起使用,则会出现此问题的另一个来源。在这种情况下,在多次迭代测试Commons IO和commons-fileupload之后,问题出在处理commons-xxx JAR文件的父类加载器上。这种情况必须加以预防。崩溃总是发生在:

fileItems = uploader.parseRequest(request);

请注意,fileItems 的 List 类型已随着 commons-fileupload 的当前版本而更改为专门,而不是以前的版本,其中它是通用的。List<FileItem>List

我将 commons-fileupload 和 Commons IO 的源代码添加到我的 Eclipse 项目中,以跟踪实际错误,并最终得到了一些见解。首先,抛出的异常类型为 Throwable,而不是所述的 FileIOException,甚至不是 Exception(这些不会被捕获)。其次,错误消息是混淆的,因为它表示找不到类,因为 axis2 找不到 commons-io。Axis2 在我的项目中根本没有使用,但它作为标准安装的一部分存在于 Geronimo 存储库子目录中的文件夹中。

最后,我找到了一个提出有效解决方案的地方,成功解决了我的问题。您必须在部署规划中对父加载程序隐藏 JAR 文件。这被放入geronimo-web.xml文件中,我的完整文件如下所示。

粘贴自 http://osdir.com/ml/user-geronimo-apache/2011-03/msg00026.html

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<web:web-app xmlns:app="http://geronimo.apache.org/xml/ns/j2ee/application-2.0" xmlns:client="http://geronimo.apache.org/xml/ns/j2ee/application-client-2.0" xmlns:conn="http://geronimo.apache.org/xml/ns/j2ee/connector-1.2" xmlns:dep="http://geronimo.apache.org/xml/ns/deployment-1.2" xmlns:ejb="http://openejb.apache.org/xml/ns/openejb-jar-2.2" xmlns:log="http://geronimo.apache.org/xml/ns/loginconfig-2.0" xmlns:name="http://geronimo.apache.org/xml/ns/naming-1.2" xmlns:pers="http://java.sun.com/xml/ns/persistence" xmlns:pkgen="http://openejb.apache.org/xml/ns/pkgen-2.1" xmlns:sec="http://geronimo.apache.org/xml/ns/security-2.0" xmlns:web="http://geronimo.apache.org/xml/ns/j2ee/web-2.0.1">
    <dep:environment>
        <dep:moduleId>
            <dep:groupId>DataStar</dep:groupId>
            <dep:artifactId>DataStar</dep:artifactId>
            <dep:version>1.0</dep:version>
            <dep:type>car</dep:type>
        </dep:moduleId>

        <!-- Don't load commons-io or fileupload from parent classloaders -->
        <dep:hidden-classes>
            <dep:filter>org.apache.commons.io</dep:filter>
            <dep:filter>org.apache.commons.fileupload</dep:filter>
        </dep:hidden-classes>
        <dep:inverse-classloading/>

    </dep:environment>
    <web:context-root>/DataStar</web:context-root>
</web:web-app>

评论

0赞 Peter Mortensen 10/28/2021
链接(实际上)已损坏(重定向到 ) - HTTPS 版本也是如此。https://osdir.com/
-4赞 rohan kamat 10/24/2013 #5

发送多个文件作为文件,我们必须使用 .enctype="multipart/form-data"

要发送多个文件,请在输入标签中使用:multiple="multiple"

<form action="upload" method="post" enctype="multipart/form-data">
    <input type="file" name="fileattachments"  multiple="multiple"/>
    <input type="submit" />
</form>

评论

2赞 CyberMew 9/29/2015
我们将如何去做 getPart(“fileattachments”) 以便我们得到一个 Parts 数组?我不认为多个文件的getPart会起作用吗?
0赞 Peter Mortensen 10/28/2021
“为文件发送多个文件”是什么意思(似乎难以理解)?请通过编辑(更改)您的答案来回复,而不是在评论中(没有“编辑:”,“更新:”或类似内容 - 问题/答案应该看起来像今天写的一样)。
12赞 joseluisbz 1/25/2014 #6

Tomcat 6 或 Tomcat 7 中没有组件或外部库

web.xml 文件中启用上传:

手动安装 PHP、Tomcat 和 Httpd Lounge

<servlet>
    <servlet-name>jsp</servlet-name>
    <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
    <multipart-config>
      <max-file-size>3145728</max-file-size>
      <max-request-size>5242880</max-request-size>
    </multipart-config>
    <init-param>
        <param-name>fork</param-name>
        <param-value>false</param-value>
    </init-param>
    <init-param>
        <param-name>xpoweredBy</param-name>
        <param-value>false</param-value>
    </init-param>
    <load-on-startup>3</load-on-startup>
</servlet>

正如你所看到的

<multipart-config>
  <max-file-size>3145728</max-file-size>
  <max-request-size>5242880</max-request-size>
</multipart-config>

使用 JSP 上载文件。文件:

在 HTML 文件中

<form method="post" enctype="multipart/form-data" name="Form" >

  <input type="file" name="fFoto" id="fFoto" value="" /></td>
  <input type="file" name="fResumen" id="fResumen" value=""/>

在 JSP 文件Servlet

InputStream isFoto = request.getPart("fFoto").getInputStream();
InputStream isResu = request.getPart("fResumen").getInputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte buf[] = new byte[8192];
int qt = 0;
while ((qt = isResu.read(buf)) != -1) {
  baos.write(buf, 0, qt);
}
String sResumen = baos.toString();

根据 servlet 要求编辑代码,例如 max-file-size、max-request-size 和其他可以设置的选项......

-1赞 Mitul Maheshwari 2/4/2014 #7

您可以使用 JSP /servlet 上载文件。

<form action="UploadFileServlet" method="post">
    <input type="text" name="description" />
    <input type="file" name="file" />
    <input type="submit" />
</form>

另一方面,在服务器端,使用以下代码。

package com.abc..servlet;

import java.io.File;
---------
--------


/**
 * Servlet implementation class UploadFileServlet
 */
public class UploadFileServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    public UploadFileServlet() {
        super();
        // TODO Auto-generated constructor stub
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        response.sendRedirect("../jsp/ErrorPage.jsp");
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub

        PrintWriter out = response.getWriter();
        HttpSession httpSession = request.getSession();
        String filePathUpload = (String) httpSession.getAttribute("path") != null ? httpSession.getAttribute("path").toString() : "" ;

        String path1 = filePathUpload;
        String filename = null;
        File path = null;
        FileItem item = null;


        boolean isMultipart = ServletFileUpload.isMultipartContent(request);

        if (isMultipart) {
            FileItemFactory factory = new DiskFileItemFactory();
            ServletFileUpload upload = new ServletFileUpload(factory);
            String FieldName = "";
            try {
                List items = upload.parseRequest(request);
                Iterator iterator = items.iterator();
                while (iterator.hasNext()) {
                     item = (FileItem) iterator.next();

                        if (fieldname.equals("description")) {
                            description = item.getString();
                        }
                    }
                    if (!item.isFormField()) {
                        filename = item.getName();
                        path = new File(path1 + File.separator);
                        if (!path.exists()) {
                            boolean status = path.mkdirs();
                        }
                        /* Start of code fro privilege */

                        File uploadedFile = new File(path + Filename);  // for copy file
                        item.write(uploadedFile);
                        }
                    } else {
                        f1 = item.getName();
                    }

                } // END OF WHILE
                response.sendRedirect("welcome.jsp");
            } catch (FileUploadException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

评论

0赞 Peter Mortensen 10/28/2021
“从特权开始代码”是什么意思(似乎难以理解)?请通过编辑(更改)您的答案来回复,而不是在评论中(没有“编辑:”,“更新:”或类似内容 - 答案应该看起来好像是今天写的)。
-1赞 Mahender Reddy Yasa 3/23/2015 #8

用:

DiskFileUpload upload = new DiskFileUpload();

您必须从此对象中获取文件项和字段,然后可以存储到服务器中,如下所示:

String loc = "./webapps/prjct name/server folder/" + contentid + extension;
File uploadFile = new File(loc);
item.write(uploadFile);
0赞 dessalines 5/22/2015 #9

下面是一个使用 apache commons-fileupload 的示例:

// apache commons-fileupload to handle file upload
DiskFileItemFactory factory = new DiskFileItemFactory();
factory.setRepository(new File(DataSources.TORRENTS_DIR()));
ServletFileUpload fileUpload = new ServletFileUpload(factory);

List<FileItem> items = fileUpload.parseRequest(req.raw());
FileItem item = items.stream()
  .filter(e ->
  "the_upload_name".equals(e.getFieldName()))
  .findFirst().get();
String fileName = item.getName();

item.write(new File(dir, fileName));
log.info(fileName);
26赞 Amila 8/26/2015 #10

如果您碰巧使用 Spring MVC,这是如何做到的(我把它留在这里,以防有人发现它有用):

使用属性设置为“”的表单(与 BalusC 的答案相同):enctypemultipart/form-data

<form action="upload" method="post" enctype="multipart/form-data">
    <input type="file" name="file" />
    <input type="submit" value="Upload"/>
</form>

在控制器中,将请求参数映射到键入类型,如下所示:fileMultipartFile

@RequestMapping(value = "/upload", method = RequestMethod.POST)
public void handleUpload(@RequestParam("file") MultipartFile file) throws IOException {
    if (!file.isEmpty()) {
            byte[] bytes = file.getBytes(); // alternatively, file.getInputStream();
            // application logic
    }
}

您可以使用 的 和 获取文件名和大小。MultipartFilegetOriginalFilename()getSize()

我已经用 Spring 版本测试了这一点。4.1.1.RELEASE

评论

0赞 Kenny Worden 7/20/2018
如果我没记错的话,这需要您在服务器的应用程序配置中配置一个 bean......
-2赞 Himanshu Patel 7/15/2016 #11

HTML 页面

<html>
    <head>
        <title>File Uploading Form</title>
    </head>

    <body>
        <h3>File Upload:</h3>
        Select a file to upload: <br />
        <form action="UploadServlet" method="post"
              enctype="multipart/form-data">

            <input type="file" name="file" size="50" />
            <br />
            <input type="submit" value="Upload File" />
        </form>
    </body>
</html>

Servlet 文件

// Import required java libraries
import java.io.*;
import java.util.*;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.output.*;

public class UploadServlet extends HttpServlet {

    private boolean isMultipart;
    private String filePath;
    private int maxFileSize = 50 * 1024;
    private int maxMemSize = 4 * 1024;
    private File file;

    public void init() {
        // Get the file location where it would be stored.
        filePath =
               getServletContext().getInitParameter("file-upload");
    }

    public void doPost(HttpServletRequest request,
                       HttpServletResponse response)
               throws ServletException, java.io.IOException {

        // Check that we have a file upload request
        isMultipart = ServletFileUpload.isMultipartContent(request);
        response.setContentType("text/html");
        java.io.PrintWriter out = response.getWriter();
        if (!isMultipart) {
            out.println("<html>");
            out.println("<head>");
            out.println("<title>Servlet upload</title>");
            out.println("</head>");
            out.println("<body>");
            out.println("<p>No file uploaded</p>");
            out.println("</body>");
            out.println("</html>");
            return;
        }

        DiskFileItemFactory factory = new DiskFileItemFactory();
        // Maximum size that will be stored in memory
        factory.setSizeThreshold(maxMemSize);
        // Location to save data that is larger than maxMemSize.
        factory.setRepository(new File("c:\\temp"));

        // Create a new file upload handler
        ServletFileUpload upload = new ServletFileUpload(factory);
        // maximum file size to be uploaded.
        upload.setSizeMax(maxFileSize);

        try {
            // Parse the request to get file items.
            List fileItems = upload.parseRequest(request);

            // Process the uploaded file items
            Iterator i = fileItems.iterator();

            out.println("<html>");
            out.println("<head>");
            out.println("<title>Servlet upload</title>");
            out.println("</head>");
            out.println("<body>");
            while (i.hasNext())
            {
                FileItem fi = (FileItem)i.next();
                if (!fi.isFormField())
                {
                     // Get the uploaded file parameters
                     String fieldName = fi.getFieldName();
                     String fileName = fi.getName();
                     String contentType = fi.getContentType();
                     boolean isInMemory = fi.isInMemory();
                     long sizeInBytes = fi.getSize();

                     // Write the file
                     if (fileName.lastIndexOf("\\") >= 0) {
                         file = new File(filePath +
                         fileName.substring(fileName.lastIndexOf("\\")));
                     }
                     else {
                         file = new File(filePath +
                         fileName.substring(fileName.lastIndexOf("\\") + 1));
                     }
                     fi.write(file);
                     out.println("Uploaded Filename: " + fileName + "<br>");
                }
            }
            out.println("</body>");
            out.println("</html>");
        }
        catch(Exception ex) {
            System.out.println(ex);
        }
    }

    public void doGet(HttpServletRequest request,
                        HttpServletResponse response)
            throws ServletException, java.io.IOException {

        throw new ServletException("GET method used with " +
                 getClass().getName() + ": POST method required.");
    }
}

文件 web.xml

编译上面的 Servlet UploadServlet,并在 web.xml 文件中创建所需的条目,如下所示。

<servlet>
   <servlet-name>UploadServlet</servlet-name>
   <servlet-class>UploadServlet</servlet-class>
</servlet>

<servlet-mapping>
   <servlet-name>UploadServlet</servlet-name>
   <url-pattern>/UploadServlet</url-pattern>
</servlet-mapping>
7赞 Shivangi Gupta 7/16/2017 #12

对于 Spring MVC

我设法有一个更简单的版本,用于获取表单输入,包括数据和图像。

<form action="/handleform" method="post" enctype="multipart/form-data">
    <input type="text" name="name" />
    <input type="text" name="age" />
    <input type="file" name="file" />
    <input type="submit" />
</form>

要处理的控制器

@Controller
public class FormController {
    @RequestMapping(value="/handleform",method= RequestMethod.POST)
    ModelAndView register(@RequestParam String name, @RequestParam int age, @RequestParam MultipartFile file)
            throws ServletException, IOException {

        System.out.println(name);
        System.out.println(age);
        if(!file.isEmpty()){
            byte[] bytes = file.getBytes();
            String filename = file.getOriginalFilename();
            BufferedOutputStream stream =new BufferedOutputStream(new FileOutputStream(new File("D:/" + filename)));
            stream.write(bytes);
            stream.flush();
            stream.close();
        }
        return new ModelAndView("index");
    }
}

评论

0赞 Onic Team 3/13/2019
你能分享db mysql中的选择图像并在jsp / html上显示吗?
-1赞 access_granted 4/26/2020 #13

我能想到的最简单的文件和输入控件方法,没有十亿个库:

  <%
      if (request.getContentType() == null)
          return;
      // For input type=text controls
      String v_Text =
          (new BufferedReader(new InputStreamReader(request.getPart("Text1").getInputStream()))).readLine();

      // For input type=file controls
      InputStream inStr = request.getPart("File1").getInputStream();
      char charArray[] = new char[inStr.available()];
      new InputStreamReader(inStr).read(charArray);
      String contents = new String(charArray);
  %>

评论

0赞 Peter Mortensen 10/28/2021
这是做什么用的?ASP.NETC#)?你能澄清一下吗?请通过编辑(更改)您的答案来回复,而不是在评论中(没有“编辑:”,“更新:”或类似内容 - 答案应该看起来好像是今天写的)。<%
0赞 Lakindu Hewawasam 11/24/2020 #14

首先必须将表单的 enctype 属性设置为“multipart/form-data”

如下所示。

<form action="Controller" method="post" enctype="multipart/form-data">
     <label class="file-upload"> Click here to upload an Image </label>
     <input type="file" name="file" id="file" required>
</form>

然后,在 Servlet “Controller” 中添加 Multi-part 的 Annotation 以指示在 Servlet 中处理多部分数据。

执行此操作后,检索通过表单发送的部分,然后检索已提交文件的文件名(带路径)。使用它在所需路径中创建一个新文件,并将文件的各个部分写入新创建的文件以重新创建该文件。

如下图所示:

@MultipartConfig

public class Controller extends HttpServlet {

    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        insertImage(request, response);
    }

    private void addProduct(HttpServletRequest request, HttpServletResponse response) {
        Part filePart = request.getPart("file");
        String imageName = Paths.get(filePart.getSubmittedFileName()).getFileName().toString();

        String imageSavePath = "specify image path to save image"; //path to save image
        FileOutputStream outputStream = null;
        InputStream fileContent = null;

        try {
            outputStream = new FileOutputStream(new File(imageSavePath + File.separator + imageName));
            // Creating a new file with file path and the file name
            fileContent = filePart.getInputStream();
            // Getting the input stream
            int readBytes = 0;
            byte[] readArray = new byte[1024];
            // Initializing a byte array with size 1024

            while ((readBytes = fileContent.read(readArray)) != -1) {
                outputStream.write(readArray, 0, readBytes);
            } // This loop will write the contents of the byte array unitl the end to the output stream
        } catch (Exception ex) {
            System.out.println("Error Writing File: " + ex);
        } finally {
            if (outputStream != null) {
                outputStream.close();
                // Closing the output stream
            }
            if (fileContent != null) {
                fileContent.close();
                // Closing the input stream
            }
        }
    }
}

评论

1赞 Lakindu Hewawasam 11/25/2020
这个解决方案是不同的。其他解决方案使用库来处理文件,因为这没有第三方 jar 文件。
1赞 BalusC 11/25/2020
目前接受的答案已经涵盖了这一点。你读过吗?本机 API 自 2009 年 12 月起就已存在。顺便说一句,您关闭流的方式也是遗留的。自 2011 年 7 月推出的 Java 7 以来,您可以使用 try-with-resources 语句,而不是在 finally 中摆弄 nullchecks。