> Java > 본문

JSP/Servlet을 사용하여 서버에 파일을 업로드하는 방법은 무엇입니까?

王林
풀어 주다: 2024-02-22 12:40:07
앞으로
779명이 탐색했습니다.

PHP 편집자 Youzi가 JSP/Servlet을 사용하여 Java로 서버에 파일을 업로드하는 방법을 소개합니다. 웹 개발에서 파일 업로드는 일반적인 요구 사항이며, JSP/Servlet을 사용하여 간단하고 효율적인 파일 업로드 기능을 구현할 수 있습니다. 다음으로는 자바 코드를 통해 서버에 파일을 업로드하는 방법을 자세히 소개하겠습니다. 이를 통해 이 기술을 빠르게 익히고 개발 능력을 향상시킬 수 있습니다.

질문 내용

jsp/servlet을 사용하여 서버에 파일을 업로드하는 방법은 무엇입니까?

이것을 시도했습니다:

으아악

하지만 파일 내용은 알 수 없고 파일 이름만 알 수 있습니다. 언제 enctype="multipart/form-data" 添加到 <form> 时,request.getparameter() 返回 null.

조사 중에 우연히 Apache 공통 파일 업로드를 발견했습니다. 나는 이것을 시도했다:

으아악

안타깝게도 명확한 메시지나 이유 없이 서블릿에서 예외가 발생했습니다. 스택 추적은 다음과 같습니다.

<form action="upload" method="post">
    <input type="text" name="description" />
    <input type="file" name="file" />
    <input type="submit" />
</form>
로그인 후 복사

솔루션

소개

업로드할 파일을 찾아 선택하려면 양식에 html을 추가해야 합니다 <input type="file"> 字段。如 HTML specification 中所述,您必须使用 post 方法,并且表单的 enctype 属性必须设置为 "multipart/form-data".

으아악

이러한 양식을 제출한 후 enctype가 설정되지 않은 경우와는 다른 형식으로 요청 본문에서 바이너리 다중 부분 양식 데이터를 사용할 수 있습니다.

서블릿 3.0(2009년 12월) 이전에는 서블릿 API 자체가 multipart/form-data。它仅支持默认形式 enctype application/x-www-form-urlencoded。当使用多部分表单数据时,request.getparameter() 和 consorts 都将返回 null를 지원하지 않았습니다. 여기가 잘 알려진 Apache Commons FileUpload가 들어오는 곳입니다.

수동으로 분석하지 마세요!

이론적으로는 ServletRequest#getInputStream()을 기반으로 요청 본문을 직접 구문 분석할 수 있습니다. 그러나 이는 RFC2388에 대한 정확한 지식이 필요한 정확하고 지루한 작업입니다. 이 작업을 직접 수행하거나 인터넷의 다른 곳에서 찾은 라이브러리 없는 직접 만든 코드를 복사하여 붙여넣어서는 안 됩니다. 이와 관련하여 roseindia.net과 같은 많은 온라인 리소스가 실패합니다. pdf 파일 업로드도 참조하세요. 수년 동안 수백만 명의 사용자가 사용해 온(그리고 암시적으로 테스트된) 실제 라이브러리를 사용해야 합니다. 이러한 라이브러리는 견고성이 입증되었습니다.

이미 서블릿 3.0 이상을 사용하고 계시다면 네이티브 API를 사용해 주세요

적어도 서블릿 3.0(tomcat 7, jetty 9, jboss as 6, glassfish 3 등은 2010년부터 사용되었습니다)을 사용하고 있다면 HttpServletRequest#getPart()를 사용할 수 있습니다. HttpServletRequest#getPart() 提供的标准 api 来收集单独的多部分表单数据项(大多数 servlet 3.0 实现实际上都在幕后使用 apache commons fileupload!)。此外,正常形式字段可以通过 getparameter() 개별 다중 부분 양식 데이터 항목을 수집하기 위한 표준 API를 제공합니다(대부분의 서블릿 3.0 구현은 실제로 뒤에서 Apache Commons FileUpload를 사용합니다!). 또한 getparameter()를 통해 일반적인 방법으로 일반 형식 필드를 얻을 수 있습니다.

먼저 서블릿에 @MultipartConfig@MultipartConfig 注释您的 servlet,以便让它识别并支持 multipart/form-data 请求,从而使 getpart() 주석을 달아 multipart/form-data 요청을 인식하고 지원하여 getpart() 작업을 활성화합니다. 일반적으로:

으아악

그런 다음 dopost() 다음과 같이 구현하세요.

으아악

주의path#getfilename(). 이것은 파일 이름 가져오기에 관한 msie 수정입니다. 이 브라우저는 파일 이름만이 아닌 전체 파일 경로와 이름을 잘못 전송합니다.

multiple="true"를 통해 여러 파일을 업로드하려면

으아악

또는 여러 입력을 사용하는 구식 방식,

으아악

다음과 같이 수집할 수 있습니다(안타깝게도 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 来解析多部分表单数据请求。它有一个很好的User GuideFAQ(仔细检查两者)。还有 o'reilly(“cos”)multipartrequest,但它有一些(小)错误,并且多年来不再积极维护。我不建议使用它。 apache commons fileupload 仍在积极维护,目前非常成熟。

为了使用 apache commons fileupload,您的 web 应用程序的 /web-inf/lib 中至少需要有以下文件:

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

下面是一个启动示例,显示使用 apache commons fileupload 时 uploadservletdopost() 的样子:

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);
    }

    // ...
}
로그인 후 복사

非常重要的是,您不要事先在同一请求上调用 getparameter()getparametermap()getparametervalues()getinputstream()getreader() 等。否则,servlet 容器将读取并解析请求正文,因此 apache commons fileupload 将得到一个空请求正文。另请参见 a.o. ServletFileUpload#parseRequest(request) returns an empty list

注意 filenameutils#getname()。这是有关获取文件名的 msie 修复。此浏览器错误地发送完整文件路径和名称,而不仅仅是文件名。

或者,您也可以将这一切包装在 filter 中,它会自动解析所有内容并将内容放回请求的参数映射中,以便您可以继续以通常的方式使用 request.getparameter() 并通过以下方式检索上传的文件request.getattribute()You can find an example in this blog article

glassfish3 中 getparameter() 错误的解决方法仍然返回 null

请注意,早于 3.1.2 的 glassfish 版本有 a bug,其中 getparameter() 仍返回 null。如果您的目标是这样的容器并且无法升级它,那么您需要借助此实用程序方法从 getpart() 中提取值:

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()!)

前往以下答案,详细了解如何将获得的 inputstream (上述代码片段中所示的 filecontent 变量)正确保存到磁盘或数据库:

提供上传的文件

请参阅以下答案,了解如何正确地将保存的文件从磁盘或数据库返回给客户端的详细信息:

ajax 表单

前往以下答案,了解如何使用 ajax(和 jquery)上传。请注意,无需为此更改用于收集表单数据的 servlet 代码!只有您响应的方式可能会改变,但这相当简单(即,不转发到 jsp,只需打印一些 json 或 xml 甚至纯文本,具体取决于负责 ajax 调用的脚本所期望的内容)。

如果您碰巧使用 Spring MVC,请按以下方法操作(我将其留在这里,以防有人发现它有用):

使用 enctype 属性设置为“multipart/form-datazqbenczqb”的表单(与 <a href="https://www.php.cn/link/8a13dab3f5ec9e22d0d1495c8c85e436">BalusC's answer</a> 相同):</p> <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:html;toolbar:false;">&lt;form action=&quot;upload&quot; method=&quot;post&quot; enctype=&quot;multipart/form-data&quot;&gt; &lt;input type=&quot;file&quot; name=&quot;file&quot; /&gt; &lt;input type=&quot;submit&quot; value=&quot;upload&quot;/&gt; &lt;/form&gt; </pre><div class="contentsignin">로그인 후 복사</div></div> <p>在您的控制器中,将请求参数 <code>file 映射到 multipartfile 类型,如下所示:

@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 对此进行了测试。

위 내용은 JSP/Servlet을 사용하여 서버에 파일을 업로드하는 방법은 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:stackoverflow.com
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
최신 이슈
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿
회사 소개 부인 성명 Sitemap
PHP 중국어 웹사이트:공공복지 온라인 PHP 교육,PHP 학습자의 빠른 성장을 도와주세요!