基于SpringBoot实现文件的上传下载

(一)概述

文件上传下载一直都是一个系统最常用也是最基本的功能点,刚好最近公司的项目上有用到这个功能,于是自己就用SpringBoot也写了一个简化的版本,已实现文件的上传和下载功能。

(二)创建项目

首先创建一个SpringBoot的项目,接着引入相关的依赖,因为涉及到数据库的操作,所以依赖会比较多一些。

2.1 依赖引入

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mybatis.spring.boot/mybatis-spring-boot-starter -->
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.1.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.9</version>
</dependency>

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>
复制代码

2.2 接口通用返回类编写

编写一个接口的通用返回体,这个在之前的博客中我专门写过,现在就直接拿来用了:

public enum ResponseCode {
    // 系统模块
    SUCCESS(0, "操作成功"),
    ERROR(1, "操作失败"),
    SERVER_ERROR(500, "服务器异常"),

    // 通用模块 1xxxx
    ILLEGAL_ARGUMENT(10000, "参数不合法"),
    REPETITIVE_OPERATION(10001, "请勿重复操作"),
    ACCESS_LIMIT(10002, "请求太频繁, 请稍后再试"),
    MAIL_SEND_SUCCESS(10003, "邮件发送成功"),

    // 用户模块 2xxxx
    NEED_LOGIN(20001, "登录失效"),
    USERNAME_OR_PASSWORD_EMPTY(20002, "用户名或密码不能为空"),
    USERNAME_OR_PASSWORD_WRONG(20003, "用户名或密码错误"),
    USER_NOT_EXISTS(20004, "用户不存在"),
    WRONG_PASSWORD(20005, "密码错误"),

    // 文件模块 3xxxx
    FILE_EMPTY(30001,"文件不能空"),
    FILE_NAME_EMPTY(30002,"文件名称不能为空"),
    FILE_MAX_SIZE(30003,"文件大小超出"),
    ;

    ResponseCode(Integer code, String msg) {
        this.code = code;
        this.msg = msg;
    }
    private Integer code;
    private String msg;
    public Integer getCode() {
        return code;
    }
    public void setCode(Integer code) {
        this.code = code;
    }
    public String getMsg() {
        return msg;
    }
    public void setMsg(String msg) {
        this.msg = msg;
    }
}
复制代码

返回体:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Result {
    private int code;
    private String message;
    private Object data;
}
复制代码

2.3 配置一下解决跨域问题的配置类

在SpringBoot中有多种解决跨域的方法,这里选择其中一种

public class WebMvcConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("*")
                .allowedMethods("POST", "GET", "PUT", "OPTIONS", "DELETE")
                .maxAge(3600)
                .allowCredentials(true);
    }
}
复制代码

到这里为止,基本的项目配置就算结束了,接下来就是功能的实现了。

(三)实现文件上传下载

3.1 创建表

首先创建一张表来记录文件的路径、名称、后缀等信息:

CREATE TABLE `file` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `filePath` varchar(255) DEFAULT NULL,
  `fileName` varchar(255) DEFAULT NULL,
  `fileSuffix` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
复制代码

3.2 编写实体类

写一个文件对象,和数据库中的字段相对应:

@Data
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@EqualsAndHashCode
public class Files implements Serializable {

    private static final long serialVersionUID=1L;
    /**
     * 文件存储路径
     */
    private String filePath;
    /**
     * 文件名称
     */
    private String fileName;
    /**
     * 文件后缀名
     */
    private String fileSuffix;

}
复制代码

3.3 配置application.properties

在配置文件中将服务端口,数据库连接方式以及文件的保存路径配置一下:

server.port=8080

spring.datasource.url=jdbc:mysql://localhost:3306/test7?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

mybatis.mapper-locations=classpath:mapper/*.xml
file.save-path=E:/temp/files
复制代码

3.4 编写Controller

新建一个类叫FileController,用来写接口,文件上传下载接口的代码已经给了注释,Spring中提供了一个MultipartFile类,用来接收前台传过来的文件,这里直接使用即可。

@RestController
@RequestMapping("/api")
public class FileController {
    @Autowired
    private FileService fileService;

    @RequestMapping(value = "/upload",method = RequestMethod.POST)
    public Result upLoadFiles(MultipartFile multipartFile){
        if (multipartFile.isEmpty()){
            return new Result(ResponseCode.FILE_EMPTY.getCode(),ResponseCode.FILE_EMPTY.getMsg(),null);
        }
        return fileService.upLoadFiles(multipartFile);
    }

    @RequestMapping(value = "/download/{id}",method = RequestMethod.GET)
    public void downloadFiles(@PathVariable("id") String id, HttpServletRequest request, HttpServletResponse response){
        OutputStream outputStream=null;
        InputStream inputStream=null;
        BufferedInputStream bufferedInputStream=null;
        byte[] bytes=new byte[1024];
        Files files = fileService.getFileById(id);
        String fileName = files.getFileName();
        // 获取输出流
        try {
            response.setHeader("Content-Disposition", "attachment;filename=" +  new String(fileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1));
            response.setContentType("application/force-download");
            inputStream=fileService.getFileInputStream(files);
            bufferedInputStream=new BufferedInputStream(inputStream);
            outputStream = response.getOutputStream();
            int i=bufferedInputStream.read(bytes);
            while (i!=-1){
                outputStream.write(bytes,0,i);
                i=bufferedInputStream.read(bytes);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                if (inputStream!=null){
                    inputStream.close();
                }
                if (outputStream!=null){
                    outputStream.close();
                }
                if (bufferedInputStream!=null){
                    bufferedInputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }

}


复制代码

所有的业务都写在service中,因此需要有fileService接口以及fileServiceImpl实现类:

public interface FileService {
    /**
     * 文件上传接口
     * @param file
     * @return
     */
    Result upLoadFiles(MultipartFile file);

    /**
     * 根据id获取文件
     * @param id
     * @return
     */
    Files getFileById(String id);

    /**
     * 根据id获取数据流
     * @param files
     * @return
     */
    InputStream getFileInputStream(Files files);
}
复制代码

fileServiceImpl实现类:

@Service
public class FileServiceImpl implements FileService {

    @Value("${file.save-path}")
    private String savePath;
    @Autowired
    private FileMapper fileMapper;

    @Override
    public Result upLoadFiles(MultipartFile file) {
        //设置支持最大上传的文件,这里是1024*1024*2=2M
        long MAX_SIZE=2097152L;
        //获取要上传文件的名称
        String fileName=file.getOriginalFilename();
        //如果名称为空,返回一个文件名为空的错误
        if (StringUtils.isEmpty(fileName)){
            return new Result(ResponseCode.FILE_NAME_EMPTY.getCode(),ResponseCode.FILE_NAME_EMPTY.getMsg(),null);
        }
        //如果文件超过最大值,返回超出可上传最大值的错误
        if (file.getSize()>MAX_SIZE){
            return new Result(ResponseCode.FILE_MAX_SIZE.getCode(),ResponseCode.FILE_MAX_SIZE.getMsg(),null);
        }
        //获取到后缀名
        String suffixName = fileName.contains(".") ? fileName.substring(fileName.lastIndexOf(".")) : null;
        //文件的保存重新按照时间戳命名
        String newName = System.currentTimeMillis() + suffixName;
        File newFile=new File(savePath,newName);
        if (!newFile.getParentFile().exists()){
            newFile.getParentFile().mkdirs();
        }
        try {
            //文件写入
            file.transferTo(newFile);
        } catch (IOException e) {
            e.printStackTrace();
        }
        //将这些文件的信息写入到数据库中
        Files files=new Files(newFile.getPath(),fileName,suffixName);
        fileMapper.insertFile(files);
        return new Result(ResponseCode.SUCCESS.getCode(),ResponseCode.SUCCESS.getMsg(),"数据上传成功");
    }

    //根据id获取文件信息
    @Override
    public Files getFileById(String id) {
        Files files = fileMapper.selectFileById(id);
        return files;
    }
    
    //将文件转化为InputStream
    @Override
    public InputStream getFileInputStream(Files files) {
        File file=new File(files.getFilePath());
        try {
            return new FileInputStream(file);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }
}
复制代码

3.5 对数据库的操作

需要将数据写入到数据库中,这里用到的是mybatis,新建一个FileMapper接口:

@Mapper
@Repository
public interface FileMapper {
    /**
     * 将数据信息插入到数据库
     * @param files
     */
    void insertFile(Files files);

    /**
     * 根据id获取文件
     * @param id
     * @return
     */
    Files selectFileById(String id);
}
复制代码

编写对应的xml文件

<?xml version="1.0" encoding="UTF8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.javayz.fileuploadanddownload.mapper.FileMapper">
    <insert id="insertFile" parameterType="com.javayz.fileuploadanddownload.entity.Files">
        insert into file(filepath,filename,filesuffix) values(#{filePath},#{fileName},#{fileSuffix});
    </insert>

    <select id="selectFileById" parameterType="string" resultType="com.javayz.fileuploadanddownload.entity.Files">
        select * from file where id=#{id};
    </select>
</mapper>
复制代码

代码已上传至github,欢迎自取:github

(四)测试

将项目运行起来,首先测试文件上传,通过postman直接上传一个文件

点击send后得到操作成功的返回值,我们可以在自己设置的路径下看到这个文件,同时在数据库中也存在该文件的信息:

接下来测试文件下载,因为是get请求,直接在浏览器中访问: http://localhost:8080/api/download/4 即可调用下载。


作者:Java鱼仔
链接:https://juejin.cn/post/6917586720309379079
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在 Spring Boot 中实现文件下载非常简单,你只需要在你的项目中引入对应的依赖,然后在你的代码中使用 Spring 提供的工具类即可。 首先,你需要在项目的 pom.xml 文件中引入 spring-boot-starter-web 依赖: ``` <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> ``` 然后你就可以在你的 Controller 中使用 Spring 提供的工具类来实现文件的上下载了。 文件示例代码如下: ``` import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.multipart.MultipartFile; @PostMapping("/upload") public void upload(@RequestParam("file") MultipartFile file) { // 使用 file.getInputStream() 和 file.getOriginalFilename() 获取文件输入流和文件名 // 然后你可以使用这些信息将文件保存到你的服务器中 } ``` 文件下载示例代码如下: ``` import org.springframework.core.io.FileSystemResource; import org.springframework.core.io.InputStreamResource; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; @GetMapping("/download") public ResponseEntity<InputStreamResource> download() throws IOException { File file = new File("/path/to/your/file.txt"); InputStreamResource resource = new InputStreamResource(new FileInputStream(file)); return ResponseEntity.ok() .header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + file.getName()) .contentType(MediaType.APPLICATION_OCTET_STREAM) .contentLength(file.length()) .body(resource); } ``` 注意, ### 回答2: Spring Boot提供了简单且方便的方式来实现文件下载的功能。以下是基于Spring Boot的文件下载实现步骤: 文件: 1. 创建Spring Boot项目并添加所需的依赖项,例如spring-boot-starter-web和spring-boot-starter-data-jpa。 2. 创建一个Controller类来处理文件请求。在该类中,使用@RequestParam注解来接收上文件,并使用MultipartFile类型来处理文件数据。 3. 在Controller类中,使用File类来创建一个新的文件,并使用transferTo()方法将上文件保存到指定的位置。 4. 在Controller类中,使用ResponseEntity来返回上成功的消息或错误消息。 文件下载: 1. 创建一个Controller类来处理文件下载请求。在该类中,使用@RequestParam注解来接收要下载文件名。 2. 在Controller类中,使用File类来获取要下载文件,并使用InputStreamResource类来将文件包装为可发送的资源。 3. 在Controller类中,使用ResponseEntity来返回文件资源,并设置响应头部信息,例如Content-Disposition来指定文件名。 4. 在客户端发出下载文件请求时,将通过Controller类提供的链接来下载文件。 在实现文件下载时,还可以添加文件大小限制、文件类型限制和安全校验等功能来提高系统的稳定性和安全性。此外,还可以使用第三方库,如Apache Common FileUpload和Apache POI来更好地处理文件的上下载。 ### 回答3: Spring Boot是一个开源的Java开发框架,可以非常方便地实现文件的上下载功能。 文件功能可以通过使用Spring Boot提供的MultipartFile类来实现。首先,需要在Spring Boot的Controller中定义一个接口来处理文件的请求。可以使用@PostMapping注解来标识这个接口处理POST请求,然后使用@RequestParam注解来指定接收文件的参数,例如@RequestParam("file") MultipartFile file。接收到文件后,可以调用MultipartFile类的transferTo()方法将文件保存到指定的路径。 文件下载功能可以通过使用Spring Boot提供的Resource类来实现。首先,需要在Spring Boot的Controller中定义一个接口来处理文件下载的请求。可以使用@GetMapping注解来标识这个接口处理GET请求,然后使用@RequestParam注解来指定接收文件名的参数,例如@RequestParam("filename") String filename。接收到文件名后,可以使用Resource类的createResource()方法创建一个Resource对象,然后使用ResponseEntity类将文件返回给客户端。 在实现文件下载功能时,还需要注意设置合适的文件保存路径和文件访问路径。可以在application.properties文件中配置文件保存路径,例如spring.servlet.multipart.location=/path/to/save/files。在文件访问路径方面,可以使用ResourceHandlerRegistry类的addResourceHandler()方法来配置文件访问路径,例如registry.addResourceHandler("/files/**").addResourceLocations("file:/path/to/save/files/")。 通过上述方式,可以很方便地使用Spring Boot实现文件的上下载功能。在实际开发中,还可以结合前端技术实现更加友好的文件下载界面。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值