SpringBoot框架如何实现上传与下载查看文件

基于SpringBoot框架,如何实现文件的上传与下载查看

提要

本项目借鉴于spring-guides/gs-uploading-files: Uploading Files :: Learn how to build a Spring application that accepts multi-part file uploads. (github.com)SpringBoot官网学习文档关于如何下载文件一章提供的演示代码;

GitHub

Download-File-Java: Demonstration How to implement file upload, client download, or view files under the springboot framework. (github.com)

本项目使用GitHub作为代码托管平台,友友们,点亮小星星是对博主莫大的支持哦!!!

演示环境

  • idea集成开发工具
  • JDK21
  • Apache Maven 3.9.4

接口设计

URL: http://localhost/files/{filename}

method: GET

query: filename-文件名

function: 查看文件

URL: http://localhost/files/download/{filename}

method: GET

query: filename-文件名

function: 下载文件

URL: http://localhost/upload

method: GET

param: file-多文件对象

function: 上传文件

单元测试

分别使用MockMvc与TestRestTemplate测试工具类,模拟客户端发送HTTP请求,对项目接口与存储服务层进行了测试;

项目文件

项目文件层次

具体实现

配置类

配置客户端上传到服务端的文件存储地址,博主是默认存放在存储静态文件的resources目录下;

@Value注解可以获取properties文件中存储的配置信息;

package test.springboot.demo.config;


import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;

/**
 * 配置存储
 **/
@Configuration
public class StorageConfigure {
   
   
    @Value("${storage.path}")
    private String location;

    public String getLocation() {
   
   
        return location;
    }

    public void setLocation(String location) {
   
   
        this.location = location;
    }

}

properties文件

存放配置的信息

spring.servlet.multipart.max-file-size=4MB
spring.servlet.multipart.max-request-size=4MB
storage.path=src/main/resources/localStorage

API层

package test.springboot.demo.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import test.springboot.demo.exception.StorageFileNotFoundException;
import test.springboot.demo.service.StorageService;

@Controller
public class FileUploadController {
   
   


    private final StorageService storageService;

    /**
     * 采用构造函数来注入StorageService对象,方便进行单测
     * @param storageService StorageService对象
     **/
     @Autowired
    public FileUploadController(StorageService storageService) {
   
   
        this.storageService = storageService;
    }

    // 与上面的构造函数一样,用于注入StorageService对象
    // @Autowired
    // private StorageService storageService;

    /**
     * 做代理,客户端可下载资源或查看资源
     * @return 文件后缀
     **/
    @GetMapping(value = {
   
   "/files/{filename:.+}", "/files/{download:.+}/{filename:.+}"})
    @ResponseBody
    public ResponseEntity<Resource> serveFile(@PathVariable(required = false) String download, @PathVariable String filename) {
   
   
        // 获取文件数据
        Resource file = storageService.loadAsResource(filename);
        // 如果文件为空就返回响应404
        if (file == null) {
   
   
            return ResponseEntity.notFound().build();
        }
        // 创建响应实体,设置状态码为200
        ResponseEntity.BodyBuilder req = ResponseEntity.status(HttpStatus.OK);
        // 如果download不为空,则执行下载,添加消息头attachment
        if (download!=null) {
   
   
            req.header(HttpHeaders.CONTENT_DISPOSITION,
                    "attachment; filename=\"" + file.getFilename() + "\"");
        }
        // 设置默认文件类型为application/octet-stream,二进制流
        String contentType = "application/octet-stream";
        if (file.getFilename() != null) {
   
   
            // 获得文件名后缀
            String ext = getFileExtension(file.getFilename());
            switch (ext) {
   
   
                case "pdf":
                    contentType = "application/pdf";
                    break;
                case "png", "gif", "jpg":
                    contentType = "image/" + ext;
                    break;
                case "jpeg":
                    contentType = "image/jpeg";
                    break;
                case "ofd", "zip":
                    contentType = "application/" + ext;
                    break;
                case "xlsx":
                    contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
                    break;
            }
        }
        // 返回封装好的响应实体
        return req.contentType(MediaType.valueOf(contentType))
                .body(file);
    }

    /**
     * 获得文件名后缀
     * @param fileName 文件名
     * @return 文件后缀
     **/
    public String getFileExtension(String fileName) {
   
   
        if (fileName.lastIndexOf(".") != -1 && fileName.lastIndexOf(".") != 0)
            return fileName.substring(fileName.lastIndexOf(".") + 1);
        else
            return "";
    }

    /**
     * 上传文件
     * @return 上传是否成功
     */
    @PostMapping("/upload")
    @ResponseBody
    public boolean handleFileUpload(@RequestParam("file") M
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值