• 表单和servlet在idea中实现文件的上传


    1.前端jsp的搭建。

    通过type=file的input标签就可以选择要上传的文件,当submit提交表单的时候就可以将选定的文件以流的形式提交。要注意的技术细节就是表单中有上传文件功能时,必须显式的将表单enctype设置为multipart/form-data,不带文件上传的表单(例如只是提交各种name/value的表单)使用的默认enctype是application/x-www-form-urlencoded。

    1. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    2. <form enctype="multipart/form-data" action="fileupload" method="post">
    3. <input type="file" name="file" >
    4. <input type="submit" value="上传文件">
    5. form>
    6. <img src="${param.img}">

     此时的jsp界面如图所示:

      选择文件后,点击上传文件按钮,会将文件相关内容以post的方式提交给/fileupload。

    2.Servlet的编写。

    文件的上传和保存到服务器本质上就是一次IO操作。服务器通过InputStream读取上传的内容,通过FileOutputStream将读取的内容保存到文件。要注意的技术细节有:

    引入commons-fileupload 1.4和commons-io 2.11,将上传的文件包装成了FileItem类型,简化了相关的操作。

    保存文件的路径设定。

    我们所有的资源访问路径(例如jsp,js,image等)其实都是按照项目的开发路径展开的,也就是项目开发路径中webapp的目录结构。

    例如有这样的项目结构:

    如果在index.jsp中显示img_1.jpeg,那index.jsp中img标签的src属性值可以使用一个相对路径:/images/img_1.jpeg

    项目部署的时候,会将项目内容从开发路径复制到部署路径。复制的时候根据TOMCAT的设定,一种是将项目打包成.war文件,将.war文件复制到部署路径下,这种方式称为archive;另一种方式就是直接带着目录结构的复制,这种方式称为exploded。

    但是,我们使用maven的webapp骨架构建的项目时,会多一层设置。项目部署时会先将项目结构复制到一个target子文件中,然后再根据target文件夹下的目录结构复制导数TOMCAT部署路径中。这就会有一个问题,项目部署后上传的文件只会保存到target下的项目结构中,没有办法影响到原项目。而且项目重新部署时,target子文件夹下的内容会被全部覆盖。

    所以正确的设置是将项目output directory直接就写成源项目webapp所在位置即可。

    正确的设置方式是:首先在IDEA中新建一个保存上传内容的文件夹,例如uploadfiles。

    然后进入File菜单下的project structure,修改exploded的output directory,路径中就是真正的项目源文件路径,不包含任何target内容。

     最后进入TOMCAT的配置,确认一下deployment 的是exploded而不是war。

     至此相关设定结束,可以开始编写处理上传文件保存的servlet了

    1. package servlets;
    2. @WebServlet(value = "/fileupload")
    3. public class FileuploadServlet extends HttpServlet {
    4. @Override
    5. protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    6. }
    7. @Override
    8. protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    9. try {
    10. DiskFileItemFactory factory = new DiskFileItemFactory();
    11. ServletFileUpload upload = new ServletFileUpload(factory);
    12. //将上传内容封装为FileItem
    13. List fileItems = upload.parseRequest(request);
    14. for (FileItem item:fileItems) {
    15. //上传文件的inputstream
    16. InputStream inputStream = item.getInputStream();
    17. //上传文件本身的名字
    18. String fileName = item.getName();
    19. //获取新建的uploadfiles文件夹的实际路径
    20. //根据之前的设定,这个路径是: 项目文件夹/src/main/webapp/uploadfiles
    21. String path = getServletContext().getRealPath("\\uploadfiles");
    22. System.out.println("服务器保存文件路径是: "+path+"\\"+fileName);
    23. //利用FileOutputStream将内容保存到服务器上
    24. FileOutputStream outputStream = new FileOutputStream(new File(path+"\\"+fileName));
    25. byte[] bytes = new byte[1024];
    26. int count=0;
    27. while ((count=inputStream.read(bytes))!=-1){
    28. outputStream.write(bytes,0,count);
    29. }
    30. inputStream.close();
    31. outputStream.close();
    32. //重定向到jsp文件,并将刚刚上传文件的路径作为img参数的值
    33. response.sendRedirect("insertuserinfo.jsp?img=/uploadfiles/"+fileName);
    34. }
    35. } catch (FileUploadException e) {
    36. throw new RuntimeException(e);
    37. }
    38. }
    39. }

    运行TOMCAT部署项目:

     上传文件的名称是df65b...934f8cdc.jpeg,点击上传文件后:

     再看一下项目结构和控制台输出:

     

    ---------------------------------------------------------------------------------------------------------------------------------最后一点,IDEA中编写的Web项目在部署到TOMCAT的时候,是不会将项目放到我们安装或配置的正经TOMCAT的webapps下的(尽管复制到TOMCAT webapps下应该才是主流的做法)。

    IDEA根据自身版本的不同,会把Web项目部署到C:\users\用户名\.IntelliJIdea2021.2下面的system\tomcat文件夹,或者C:\Users\pigli\AppData\Local\JetBrains\IntelliJIdea2022.2下面的tomcat文件夹下。每个编码文件夹对应一个项目:

     这个文件夹就是这就是副本Tomcat目录。点进去一个其实可以看出和原生的目录大体一致,但是缺少了bin目录、lib目录、temp目录。

     

    虽然这是副本目录,但是运行是依靠原生的Tomcat去运行(这里的意思就是 idea在运行项目的时候启动的依旧是原生Tomcat),原生TOMCAT会通过一些环境变量的设置去访问副本的Tomcat。所以就不用把这些项目内容复制到原生TOMCAT的webapps文件夹下了。

    继续点击项目文件夹下conf\Catalina\localhost\ROOT.xml,docBase属性就是一个项目的output directory设定:

    这是经过修改,output directory直接是项目目录结构。上传文件时,会直接将文件保存到原项目webapp下的目录结构中,通过相对路径访问也是没有问题。

    <Context path="" docBase="D:\JavaProjects\servlettest\src\main\webapp" />

    下面的docBase是利用maven webapp骨架创建的web_mod模块的output directory。

    <Context path="" docBase="D:\JavaProjects\mytestempty\web_mod\target\web_mod.war" />

    如果在web_mod中进行相关的文件上传,可能就会出现路径问题。

  • 相关阅读:
    Flutter开发- iOS 问题CocoaPods not installed or not in valid state
    如何在 Azure 容器应用程序上部署具有 Elastic Observability 的 Hello World Web 应用程序
    Flutter 混合开发调试
    Unity URP 渲染管线:URP渲染管线光照机制剖析
    react租房项目实战 1 项目介绍、项目搭建
    提升测试工具开发的思考
    【数字IC基础】时序分析之关键路径(Critical Path)、优化方法
    OceanBase携手天阳科技推出新一代信用卡核心系统联合解决方案,为信用卡业务稳健增长提供创新活力与数据动力
    基于Restful的WebService
    IP网络广播景区广播广播系统
  • 原文地址:https://blog.csdn.net/piglite/article/details/128199955