Spring-MVC的文件上传,下载的技术攻克

简介: Spring-MVC的文件上传,下载的技术攻克

一.前言      

       SpringMVC的文件上传下载的主要作用是让用户能够将文件上传到服务器或从服务器下载文件。这对于许多 Web 应用程序来说是非常重要的功能,例如,当用户需要上传头像或其他文件时,或者当需要在 Web 应用程序中提供可下载的文件时,都需要使用文件上传下载的功能。Spring MVC提供了方便的机制来实现文件上传和下载的功能。

二.文件上传

     文件上传的步骤:

  1. 导入pom.xml依赖
  2. spring-mvc.xml,配置多功能视图解析器
  3. 前端在表单标记为多功能表单 enctype=" mutipart/form=data"
  4. 后端利用mutipartFile类,接受前端传递到后台的文件
  5. 将文件转成流,然后写入到服务器(某一个硬盘)
  6. 做硬盘与网络地址的映射(服务器配置)

      第一步,先导入pom.xml依赖文件

<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.3.3</version>
</dependency>

       第二步,配置多功能视图解析器

<!--添加文件上传解析器-->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <!-- 必须和用户JSP 的pageEncoding属性一致,以便正确解析表单的内容 -->
        <property name="defaultEncoding" value="UTF-8"></property>
        <!-- 文件最大大小(字节) 1024*1024*50=50M-->
        <property name="maxUploadSize" value="52428800"></property>
        <!--resolveLazily属性启用是为了推迟文件解析,以便捕获文件大小异常-->
        <property name="resolveLazily" value="true"/>
    </bean>

       第三步 ,前端在表单标记为多功能表单 enctype=" mutipart/form=data"

     第四步

              建立一个通用跳转页面的,这样就可以不用再去写一个方法了

package com.yinzi.web;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
/**
 * @author yinzi
 * @create 2023-09-09 14:50
 */
@Controller
public class PageController {
    @RequestMapping("/page/{page}")
    public String toPage(@PathVariable("page") String page){
        return page;
    }
    @RequestMapping("/page/{dir}/{page}")
    public String toDirPage(@PathVariable("dir") String dir,
                            @PathVariable("page") String page){
        return dir + "/" + page;
    }
}

       在建立一个upload的文件上传的配置文件

      读取配置文件,下载到数据库中

package com.yinzi.util;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
public class PropertiesUtil {
  public static String getValue(String key) throws IOException {
    Properties p = new Properties();
    InputStream in = PropertiesUtil.class.getResourceAsStream("/upload.properties");
    p.load(in);
    return p.getProperty(key);
  }
}

后台核心代码

/**
 * @author yinzi
 * @create 2023-09-09 14:07
 */
@Controller  //代替之前的自定义mvc的ActionSupport
@RequestMapping("/struts")
public class StrutsController {
    @Autowired
    private StrutsBiz strutsBiz;
    @RequestMapping("/list")
    public String list(Struts struts, HttpServletRequest request){
        //分页
        PageBean pageBean=new PageBean();
        pageBean.setRequest(request);
        //调用查询方法
        List<Struts> struts1 = strutsBiz.selectList(struts, pageBean);
        request.setAttribute("list",struts1);
        request.setAttribute("pageBean",pageBean);
        return "list";
    }
     @RequestMapping("/upload")
    public String upload(Struts struts ,MultipartFile cfile) throws IOException {
        //图片存放的地址
        String dir= PropertiesUtil.getValue("dir");
        //网络访问地址
        String server=PropertiesUtil.getValue("server");
        String filename = cfile.getOriginalFilename();
        FileUtils.copyInputStreamToFile(cfile.getInputStream(),new File(dir+filename));
       //保存
        struts.setPic(server+filename);
        strutsBiz.updateByPrimaryKeySelective(struts);
        return "redirect:list";
    }
}

      前台核心代码

<body>
<form class="form-inline"
      action="${pageContext.request.contextPath }/struts/list" method="post">
    <div class="form-group mb-2">
        <input type="text" class="form-control-plaintext" name="cname"
               placeholder="请输入名称">
    </div>
    <button type="submit" class="btn btn-primary mb-2">查询</button>
  <a class="btn btn-primary mb-2" href="${pageContext.request.contextPath }/struts/edit">新增</a>
</form>
<table class="table table-striped ">
    <thead>
    <tr>
        <th scope="col">ID</th>
        <th scope="col">班级</th>
        <th scope="col">教员</th>
        <th scope="col">图片</th>
        <th scope="col">操作</th>
    </tr>
    </thead>
    <tbody>
    <c:forEach  var="b" items="${list}">
        <tr>
            <td>${b.cid }</td>
            <td>${b.cname }</td>
            <td>${b.cteacher }</td>
            <td>
                <img src="${b.pic }" style="height: 100px;width: 60px">
            </td>
            <td>
   <%--           <a href="${pageContext.request.contextPath }/struts/edit?cid=${b.cid}">修改</a>
                <a href="${pageContext.request.contextPath }/struts/del?cid=${b.cid}">删除</a>--%>
                <a href="${pageContext.request.contextPath }/page/upload?cid=${b.cid}">图片上传</a>
            </td>
        </tr>
    </c:forEach>
    </tbody>
</table>
<!-- 这一行代码就相当于前面分页需求前端的几十行了 -->
<z:page pageBean="${pageBean }"></z:page>
${pageBean }
</body>

       测试结果:

三.文件下载

      文件下载就是照猫画虎

      后台核心代码:

/*文件下载*/
@RequestMapping(value="/download")
public ResponseEntity<byte[]> download(Struts struts, HttpServletRequest req){
    try {
        //先根据文件id查询对应图片信息
        Struts struts1 = this.strutsBiz.selectByPrimaryKey(struts.getCid());
        String diskPath = PropertiesUtil.getValue("dir");
        String reqPath = PropertiesUtil.getValue("server");
        String realPath = struts1.getPic().replace(reqPath,diskPath);
        String fileName = realPath.substring(realPath.lastIndexOf("/")+1);
        //下载关键代码
        File file=new File(realPath);
        HttpHeaders headers = new HttpHeaders();//http头信息
        String downloadFileName = new String(fileName.getBytes("UTF-8"),"iso-8859-1");//设置编码
        headers.setContentDispositionFormData("attachment", downloadFileName);
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        //MediaType:互联网媒介类型  contentType:具体请求中的媒体类型信息
        return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file),headers, HttpStatus.OK);
    }catch (Exception e){
        e.printStackTrace();
    }
    return null;
}

      在前台就一个文件下载的按钮即可

       测试结果:        

四.多文件上传                                                                                  

和上面的区别就是在表单里面加一个属性 multiple即可

前端核心代码:

后端核心代码:

/*多文件*/
    @RequestMapping("/uploads")
    public String uploads(HttpServletRequest req, Struts struts, MultipartFile[] files){
        try {
            StringBuffer sb = new StringBuffer();
            for (MultipartFile cfile : files) {
                //思路:
                //1) 将上传图片保存到服务器中的指定位置
                String dir = PropertiesUtil.getValue("dir");
                String server = PropertiesUtil.getValue("server");
                String filename = cfile.getOriginalFilename();
                FileUtils.copyInputStreamToFile(cfile.getInputStream(),new File(dir+filename));
                sb.append(filename).append(",");
            }
            System.out.println(sb.toString());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "redirect:list";
    }
}

测试结果:

今天的分享就到这啦!!

相关文章
|
3月前
|
开发框架 负载均衡 Java
当热门技术负载均衡遇上 Spring Boot,开发者的梦想与挑战在此碰撞,你准备好了吗?
【8月更文挑战第29天】在互联网应用开发中,负载均衡至关重要,可避免单服务器过载导致性能下降或崩溃。Spring Boot 作为流行框架,提供了强大的负载均衡支持,通过合理分配请求至多台服务器,提升系统可用性与可靠性,优化资源利用。本文通过示例展示了如何在 Spring Boot 中配置负载均衡,包括添加依赖、创建负载均衡的 `RestTemplate` 实例及服务接口调用等步骤,帮助开发者构建高效、稳定的应用。随着业务扩展,掌握负载均衡技术将愈发关键。
75 6
|
1月前
|
存储 Java API
简单两步,Spring Boot 写死的定时任务也能动态设置:技术干货分享
【10月更文挑战第4天】在Spring Boot开发中,定时任务通常通过@Scheduled注解来实现,这种方式简单直接,但存在一个显著的限制:任务的执行时间或频率在编译时就已经确定,无法在运行时动态调整。然而,在实际工作中,我们往往需要根据业务需求或外部条件的变化来动态调整定时任务的执行计划。本文将分享一个简单两步的解决方案,让你的Spring Boot应用中的定时任务也能动态设置,从而满足更灵活的业务需求。
83 4
|
5月前
|
XML Java 数据格式
技术好文:Spring基础篇——AOP切面编程
技术好文:Spring基础篇——AOP切面编程
|
2月前
|
存储 缓存 Java
在Spring Boot中使用缓存的技术解析
通过利用Spring Boot中的缓存支持,开发者可以轻松地实现高效和可扩展的缓存策略,进而提升应用的性能和用户体验。Spring Boot的声明式缓存抽象和对多种缓存技术的支持,使得集成和使用缓存变得前所未有的简单。无论是在开发新应用还是优化现有应用,合理地使用缓存都是提高性能的有效手段。
39 1
|
2月前
|
前端开发 安全 Java
技术进阶:使用Spring MVC构建适应未来的响应式Web应用
【9月更文挑战第2天】随着移动设备的普及,响应式设计至关重要。Spring MVC作为强大的Java Web框架,助力开发者创建适应多屏的应用。本文推荐使用Thymeleaf整合视图,通过简洁的HTML代码提高前端灵活性;采用`@ResponseBody`与`Callable`实现异步处理,优化应用响应速度;运用`@ControllerAdvice`统一异常管理,保持代码整洁;借助Jackson简化JSON处理;利用Spring Security增强安全性;并强调测试的重要性。遵循这些实践,将大幅提升开发效率和应用质量。
63 7
|
3月前
|
缓存 NoSQL Java
SpringBoot的三种缓存技术(Spring Cache、Layering Cache 框架、Alibaba JetCache 框架)
Spring Cache 是 Spring 提供的简易缓存方案,支持本地与 Redis 缓存。通过添加 `spring-boot-starter-data-redis` 和 `spring-boot-starter-cache` 依赖,并使用 `@EnableCaching` 开启缓存功能。JetCache 由阿里开源,功能更丰富,支持多级缓存和异步 API,通过引入 `jetcache-starter-redis` 依赖并配置 YAML 文件启用。Layering Cache 则提供分层缓存机制,需引入 `layering-cache-starter` 依赖并使用特定注解实现缓存逻辑。
956 1
SpringBoot的三种缓存技术(Spring Cache、Layering Cache 框架、Alibaba JetCache 框架)
|
2月前
|
JavaScript 前端开发 Java
【颠覆传统】Spring框架如何用WebSocket技术重塑实时通信格局?揭秘背后的故事与技术细节!
【9月更文挑战第4天】随着Web应用对实时交互需求的增长,传统的HTTP模型已无法满足现代应用的要求,特别是在需要持续、双向通信的场景下。WebSocket协议由此诞生,提供全双工通信渠道,使服务器与客户端能实时互发消息。作为Java开发中最受欢迎的框架之一,Spring通过其WebSocket模块支持这一协议,简化了WebSocket在Spring应用中的集成。
55 0
|
3月前
|
前端开发 Java Spring
Spring与Angular/React/Vue:当后端大佬遇上前端三杰,会擦出怎样的火花?一场技术的盛宴,你准备好了吗?
【8月更文挑战第31天】Spring框架与Angular、React、Vue等前端框架的集成是现代Web应用开发的核心。通过RESTful API、WebSocket及GraphQL等方式,Spring能与前端框架高效互动,提供快速且功能丰富的应用。RESTful API简单有效,适用于基本数据交互;WebSocket支持实时通信,适合聊天应用和数据监控;GraphQL则提供更精确的数据查询能力。开发者可根据需求选择合适的集成方式,提升用户体验和应用功能。
92 0
|
3月前
|
Java 数据库连接 数据库
告别繁琐 SQL!Hibernate 入门指南带你轻松玩转 ORM,解锁高效数据库操作新姿势
【8月更文挑战第31天】Hibernate 是一款流行的 Java 持久层框架,简化了对象关系映射(ORM)过程,使开发者能以面向对象的方式进行数据持久化操作而无需直接编写 SQL 语句。本文提供 Hibernate 入门指南,介绍核心概念及示例代码,涵盖依赖引入、配置文件设置、实体类定义、工具类构建及基本 CRUD 操作。通过学习,你将掌握使用 Hibernate 简化数据持久化的技巧,为实际项目应用打下基础。
181 0
|
3月前
|
Java 前端开发 Spring
技术融合新潮流!Vaadin携手Spring Boot、React、Angular,引领Web开发变革,你准备好了吗?
【8月更文挑战第31天】本文探讨了Vaadin与Spring Boot、React及Angular等主流技术栈的最佳融合实践。Vaadin作为现代Java Web框架,与其他技术栈结合能更好地满足复杂应用需求。文中通过示例代码展示了如何在Spring Boot项目中集成Vaadin,以及如何在Vaadin项目中使用React和Angular组件,充分发挥各技术栈的优势,提升开发效率和用户体验。开发者可根据具体需求选择合适的技术组合。
73 0