文件上传与下载

文件上传与下载

在Spring Boot中实现文件上传与下载的功能通常涉及前端和后端的交互。前端负责提供文件选择的界面和触发上传/下载操作,后端则负责处理文件上传的请求、存储文件,以及处理文件下载的请求并发送文件内容给前端。

文件上传

  1. 前端:使用HTML表单或JavaScript库来选择文件并发送POST请求到后端。
  2. 后端:在Spring Boot中,你可以使用MultipartFile接口来处理文件上传。下面是一个简单的示例。

前端

html 复制代码
<div class="container">
    <h1 class="title">文件上传</h1>
    <form action="/uploadFile" enctype="multipart/form-data" method="post">
        <div class="upload-area">
            <input type="file" id="fileInput" name="files"
             multiple onchange="updateFileList(this)">
            <button type="submit" >上传文件</button>
        </div>
        <ul id="fileList" class="file-list"></ul>
    </form>

        <p id="uploadSuccess" class="upload-success" 
        th:text="${uploadStatus}">文件上传成功!</p>

</div>

后端Controller示例:

实体表

java 复制代码
@Data
@TableName("attachment")
public class Attachment {
    @TableId(type = IdType.AUTO)
    private Long id;
    private String fileName;
    private String storagePath;
}

上传页面访问方法

java 复制代码
@Controller
public class FileController {

    @Autowired
    private IAttachmentService attachmentService;

    // 向文件上传页面跳转
    @GetMapping("/toUpload")
    public String upload(){
        return "upload";
    }
}

文件上传方法

java 复制代码
  //文件上传管理
    @PostMapping("/uploadFile")
    public String uploadFile(MultipartFile[] files, Model model){
        // 默认文件上传成功,并返回状态信息
        model.addAttribute("uploadStatus", "上传成功!");
        for(MultipartFile file:files){
            // 获取文件名以及后缀名
            String fileName = file.getOriginalFilename();
            // 重新生成文件名(根据具体情况生成对应文件名)
            fileName = UUID.randomUUID()+"_"+fileName;
            // 指定上传文件本地存储目录,不存在需要提前创建
            String dirPath = "D:/file/";
            File filePath = new File(dirPath);
            if(!filePath.exists()){
                filePath.mkdirs();
            }
            try {
                file.transferTo(new File(dirPath+fileName));
                //文件信息存储到数据库中
                Attachment attachment = new Attachment();
                attachment.setFileName(file.getOriginalFilename());
                attachment.setStoragePath(fileName);
                attachmentService.save(attachment);
            } catch (Exception e) {
                e.printStackTrace();
                // 上传失败,返回失败信息
                model.addAttribute("uploadStatus","上传失败: "+e.getMessage());
            }
        }
        // 携带上传状态信息回调到文件上传页面
        return "upload";
    }

文件下载

前端:用户点击下载链接或按钮,触发GET请求到后端。

后端:在后端Controller中处理GET请求,读取文件内容,并将其作为HTTP响应返回给前端。

前端

html 复制代码
    <h1>文件下载列表</h1>  
    <div class="file-list" >
        <div class="file-item" th:each="attachment:${list}">
            <p class="file-name" th:text="${attachment.fileName}">文件名1</p>
            <a th:href="${'/download?id='+attachment.id}" 
            class="download-button" download>下载</a>
        </div>
        <!-- 添加更多文件项 -->  
    </div>  

下载页面访问方法

java 复制代码
 /**
     * 向文件下载页面跳转
     */
    @GetMapping("/toDownload")
    public String toDownload(Model model){
        //查询文件信息
        List<Attachment> list = attachmentService.list();
        model.addAttribute("list",list);
        return "download";
    }

文件下载方法

java 复制代码
     // 文件下载
    @GetMapping("/download")
    public ResponseEntity<Resource> fileDownload(HttpServletRequest request,Long id)
     throws Exception{
        //获取文件数据对象
        Attachment attachment = attachmentService.getById(id);
        // 指定要下载的文件根路径
        String dirPath = "D:/file/";
        // 创建该文件对象
        File file = new File(dirPath + attachment.getStoragePath());
        // 设置响应头
        HttpHeaders headers = new HttpHeaders();
        // 通知浏览器以下载方式打开(下载前对文件名进行转码)
        String filename=getFilename(request,attachment.getFileName());
        headers.setContentDispositionFormData("attachment",filename);
        // 定义以流的形式下载返回文件数据
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        InputStreamResource inputStreamResource =
         new InputStreamResource(Files.newInputStream(file.toPath()));
        return new ResponseEntity<>(inputStreamResource, headers, HttpStatus.OK);
    }

文件名乱码处理方法

java 复制代码
 // 根据浏览器的不同进行编码设置,返回编码后的文件名
    private String getFilename(HttpServletRequest request, String filename)
            throws Exception {
        // IE不同版本User-Agent中出现的关键词
        String[] IEBrowserKeyWords = {"MSIE", "Trident", "Edge"};
        // 获取请求头代理信息
        String userAgent = request.getHeader("User-Agent");
        for (String keyWord : IEBrowserKeyWords) {
            if (userAgent.contains(keyWord)) {
                //IE内核浏览器,统一为UTF-8编码显示,并对转换的+进行更正
                return URLEncoder.encode(filename, "UTF-8").replace("+"," ");
            }
        }
        //火狐等其它浏览器统一为ISO-8859-1编码显示
        return new String(filename.getBytes("UTF-8"), "ISO-8859-1");
    }

效果测试

文件上传


文件下载页面

相关推荐
xiaoqiMikko12 小时前
Dependabot 面板全绿,不代表你的 Tomcat 没洞
java·spring boot
摇滚侠13 小时前
SpringBoot 官网 阅读笔记 启用生产就绪功能 端点
spring boot·笔记·后端
evans在进步13 小时前
HashMap 为什么线程不安全?ConcurrentHashMap 如何解决?
java·spring boot·spring
小林敲代码778818 小时前
Spring Boot 3 升级踩坑:aj-captcha 行为验证码底图加载失效
java·spring boot·后端
程序员阿明19 小时前
spring boot3访问resources下的文件,使得在浏览器url中可以直接访问
java·spring boot·后端
霸道流氓气质19 小时前
SpringBoot中使用OAuth2 认证与 JWT Token — 概念、原理与实践
java·spring boot·后端
snow@li20 小时前
Vue Axios封装与SpringBoot Payload封装全景关联分析(前后端数据交互底层闭环)
前端·vue.js·spring boot
用户31268748772020 小时前
Spring Boot 日志体系到底怎么加载的?从 Logback 到 MDC 的全链路拆解
spring boot
paopaokaka_luck21 小时前
基于springboot3+vue3的云南本土影视文旅推荐平台(协同过滤算法、Echarts图形化分析)
前端·spring boot·学习·算法·echarts·mybatis
snow@li21 小时前
SpringBoot:依赖注入(DI)全景深度梳理与实战分析/@Autowired、@Resource、@Qualifier
java·spring boot·rpc