如何基于SpringWeb MultipartFile实现文件上传、下载功能

 更新时间:2024年07月20日 08:40:53   作者:JavaEdge.  
在做项目时,后端经常采用上传文件组件MultipartFile,下面这篇文章主要给大家介绍了关于如何基于SpringWeb MultipartFile实现文件上传、下载功能的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下

前言

在Web开发中,文件上传是一个常见的功能需求。Spring框架提供了MultipartFile接口,用于处理文件上传请求。MultipartFile可以代表一个多部分文件上传请求中的一个文件,提供了一系列方法用于获取文件的各种属性和内容,使得在后端处理文件上传变得十分方便。下面我们将介绍MultipartFile在Web应用中的几种常见使用场景。

1. 图片上传

在Web应用中,图片上传是一种常见的场景。用户需要上传头像、相片、证件照等图片文件,而后端需要接收并保存这些文件。使用MultipartFile接口可以轻松地实现图片文件的接收和处理。通过获取文件的原始文件名、内容类型、大小等属性,我们可以实现对图片文件的有效管理和存储。例如,我们可以将图片文件保存到服务器的文件系统中,或者将其存储到云存储服务中。

2. 文件下载

除了文件上传,文件下载也是Web应用中常见的功能需求。使用MultipartFile接口,我们可以实现文件的下载功能。在服务器端,我们可以将文件作为MultipartFile对象进行处理,并通过设置响应头信息,将文件作为下载内容返回给客户端。客户端接收到文件后,可以将其保存到本地磁盘或进行其他处理。

3. 文件编辑

在Web应用中,有时候用户需要对上传的文件进行编辑操作,例如修改文件名、修改文件内容等。使用MultipartFile接口,我们可以实现对文件的编辑功能。首先,我们可以通过MultipartFile接口获取上传的文件对象,然后对其进行相应的编辑操作。例如,我们可以修改文件的名称、修改文件的内容等。编辑完成后,我们可以将修改后的文件保存到服务器或返回给客户端。

4. 文件预览和展示

在Web应用中,有时候我们需要将上传的文件进行预览或展示。例如,在文档管理系统中,用户需要预览或下载文档文件。使用MultipartFile接口,我们可以实现文件的预览和展示功能。我们可以将文件作为MultipartFile对象进行处理,然后将其内容转换为适当的格式进行展示。例如,对于PDF文件,我们可以使用PDF阅读器插件进行展示;对于图片文件,我们可以将其直接展示在网页上。

5. 文件批量上传和处理

在实际应用中,有时候用户需要批量上传多个文件,并对这些文件进行处理。使用MultipartFile接口,我们可以实现文件的批量上传和处理功能。我们可以将多个文件作为一个多部分文件上传请求进行处理,然后对每个文件进行相应的操作。例如,我们可以将多个图片文件批量上传到服务器,并对它们进行压缩、裁剪等处理。

代码

package com.javagpt.back.controller;

import com.javagpt.application.context.UserAppContextHolder;
import com.javagpt.application.file.FileApplicationService;
import com.javagpt.application.file.FileDTO;
import com.javagpt.common.annotation.RespSuccess;
import com.javagpt.common.constant.EMConstant;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;

@Api(tags = "文件接口")
@Slf4j
@RestController
@RequestMapping(EMConstant.API_V1 + "/file")
@RespSuccess
@RequiredArgsConstructor
public class FileController {

    private final FileApplicationService fileApplicationService;

    @ApiOperation("通用文件上传")
    @PostMapping(value = "/uploadFile")
    public FileDTO uploadFile(@RequestParam("file") MultipartFile multipartFile) throws IOException {
        Long enterpriseId = UserAppContextHolder.getCurrentUser().getEnterpriseId();
        FileDTO fileDTO = fileApplicationService.saveFile(enterpriseId, multipartFile);
        return fileDTO;
    }

    //@PreAuthorize("hasAuthority('mp:file:download')")
    @ApiOperation("下载文件")
    @GetMapping(value = "/downloadFile")
    public void download(@RequestParam(value = "id") Long id, HttpServletResponse response) throws IOException {
        fileApplicationService.downloadFile(response, id, UserAppContextHolder.getCurrentUser().getEnterpriseId());
    }

    @ApiOperation("查看文件信息")
    @GetMapping(value = "/info")
    public FileDTO fileInfo(@RequestParam(value = "id") Long id) throws IOException {
        return fileApplicationService.findById(id);
    }

    @ApiOperation("下载视频")
    @GetMapping(value = "/downloadFile2")
    public void download2(@RequestParam(value = "id") Long id, HttpServletRequest request, HttpServletResponse response) throws IOException {
        fileApplicationService.downloadVideo(request, response, id, UserAppContextHolder.getCurrentUser().getEnterpriseId());
    }
}
package com.javagpt.application.file;

import com.javagpt.common.exception.BusinessRuntimeException;
import com.javagpt.common.oos.OssService;
import com.javagpt.common.util.ModelUtils;
import com.javagpt.common.util.SpringResponseUtils;
import com.javagpt.file.entity.FileEntity;
import com.javagpt.file.repository.FileRepository;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;

@Service
@Slf4j
@RequiredArgsConstructor
public class FileApplicationService {

    private final OssService ossService;

    private final FileRepository fileRepository;


    public FileDTO findById(Long id) {
        FileEntity fileEntity = fileRepository.findById(id);
        return ModelUtils.convert(fileEntity, FileDTO.class);
    }

    @Transactional
    public FileDTO saveFile(Long enterpriseId, MultipartFile file) {
        FileEntity fileEntity = saveFile(enterpriseId, file, null);
        return ModelUtils.convert(fileEntity, FileDTO.class);
    }

    @Transactional
    public FileEntity saveFile(Long enterpriseId, MultipartFile file, String fileName) {
        String originalFilename = file.getOriginalFilename();
        String name = StringUtils.isBlank(fileName) ? FilenameUtils.getBaseName(originalFilename) : fileName;
        String suffix = FilenameUtils.getExtension(originalFilename);
        long size = file.getSize();
        FileEntity fileEntity = new FileEntity();
        fileEntity.setName(name).setSuffix(suffix).setSize(size).setEnterpriseId(enterpriseId);
        fileEntity = fileEntity.save();
        String key = fileEntity.getPath();
        InputStream inputStream = null;
        try {
            inputStream = file.getInputStream();
        } catch (IOException e) {
            log.error("saveFile error:", e);
            throw BusinessRuntimeException.error("上传文件失败");
        }
        ossService.uploadFile(inputStream, key);
        IOUtils.closeQuietly(inputStream);
        return fileEntity;
    }


    @Transactional
    public FileEntity saveFile(File file) {
        long size = file.length();
        FileEntity fileEntity = new FileEntity();
        String baseName = FilenameUtils.getBaseName(file.getName());
        String extension = FilenameUtils.getExtension(file.getName());
        fileEntity.setName(baseName).setSuffix(extension).setSize(size);
        fileEntity = fileEntity.save();
        String key = fileEntity.getPath();
        FileInputStream inputStream = null;
        try {
            inputStream = new FileInputStream(file);
            ossService.uploadFile(inputStream, key);
        } catch (FileNotFoundException e) {
            log.error("saveFile error:", e);
            throw BusinessRuntimeException.error("上传文件失败");
        }
        IOUtils.closeQuietly(inputStream);
        return fileEntity;
    }


    public void downloadFile(HttpServletResponse response, Long fileId, Long enterpriseId) throws IOException {
        FileEntity fileEntity = fileRepository.findById(fileId);
        if (fileEntity == null) {
            throw BusinessRuntimeException.error("无效的文件Id");
        }
        String key = fileEntity.getPath();
        InputStream inputStream = ossService.downloadFile(key);
        SpringResponseUtils.writeAndFlushResponse(inputStream, response, fileEntity.fileFullName());
    }


    public void downloadVideo(HttpServletRequest request, HttpServletResponse response, Long fileId, Long enterpriseId) throws IOException {

        FileEntity fileEntity = fileRepository.findById(fileId);
        if (fileEntity == null) {
            throw BusinessRuntimeException.error("无效的文件Id");
        }
        response.setHeader(HttpHeaders.ACCEPT_RANGES, "bytes");
        Long fileSize = fileEntity.getSize();
        long start = 0, end = fileSize - 1;
        //判断前端需不需要分片下载
        if (StringUtils.isNotBlank(request.getHeader("Range"))) {
            response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
            String numRange = request.getHeader("Range").replaceAll("bytes=", "");
            String[] strRange = numRange.split("-");
            if (strRange.length == 2) {
                start = Long.parseLong(strRange[0].trim());
                end = Long.parseLong(strRange[1].trim());
                //若结束字节超出文件大小 取文件大小
                if (end > fileSize - 1) {
                    end = fileSize - 1;
                }
            } else {
                //若只给一个长度  开始位置一直到结束
                start = Long.parseLong(numRange.replaceAll("-", "").trim());
            }
        }
        long rangeLength = end - start + 1;
        String contentRange = new StringBuffer("bytes ").append(start).append("-").append(end).append("/").append(fileSize).toString();
        response.setHeader(HttpHeaders.CONTENT_RANGE, contentRange);
        response.setHeader(HttpHeaders.CONTENT_LENGTH, String.valueOf(rangeLength));
        String key = fileEntity.getPath();
        InputStream inputStream = ossService.downloadFile2(key, start, end);
        SpringResponseUtils.writeAndFlushResponse(inputStream, response, fileEntity.fileFullName());
    }
}

总之,MultipartFile接口在Web应用中具有广泛的应用场景,可以实现文件上传、下载、编辑、预览和批量处理等功能。通过熟练掌握MultipartFile接口的使用方法和技巧,我们可以更加高效地处理文件上传和下载请求,提升Web应用的用户体验和功能性能。

总结

到此这篇关于如何基于SpringWeb MultipartFile实现文件上传、下载功能的文章就介绍到这了,更多相关SpringWeb MultipartFile文件上传下载内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java利用位运算实现比较两个数的大小

    Java利用位运算实现比较两个数的大小

    这篇文章主要为大家介绍了,在Java中如何不用任何比较判断符(>,==,<),返回两个数( 32 位整数)中较大的数,感兴趣的可以了解一下
    2022-08-08
  • Mybatis有查询结果但存不进实体类的解决方案

    Mybatis有查询结果但存不进实体类的解决方案

    这篇文章主要介绍了Mybatis有查询结果但存不进实体类的解决方案,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-11-11
  • idea http request无法识别环境变量的解决步骤

    idea http request无法识别环境变量的解决步骤

    AlibabaCloudToolkit插件安装后在 Editor->File Types增加 AlibabaCloudROStemplates(JSON)项且会配置为解析*.json 文件,导致http client无法正确解析http-client.env.json文件而无法读取环境变量,本文介绍idea http request无法识别环境变量问题,需要的朋友可以参考下
    2023-08-08
  • Java实现月饼的制作、下单和售卖功能

    Java实现月饼的制作、下单和售卖功能

    这篇文章主要介绍了Java实现月饼的制作、下单和售卖,借此机会,我们用Lambda实现一遍月饼制作,下单,售卖的开发设计模式,主要有制作月饼的工厂模式,结合实例代码给大家介绍的非常详细,需要的朋友可以参考下
    2022-09-09
  • springboot+redis自定义注解实现发布订阅的实现代码

    springboot+redis自定义注解实现发布订阅的实现代码

    在Redis中客户端可以通过订阅特定的频道来接收发送至该频道的消息,本文主要介绍了springboot+redis自定义注解实现发布订阅,具有一定的参考价值,感兴趣的可以了解一下
    2023-08-08
  • Java中的值传递和引用传递区别解析

    Java中的值传递和引用传递区别解析

    这篇文章主要介绍了Java中的值传递和引用传递区别解析,引用类型的变量保存引用值,“引用值”指向内存空间的地址,代表了某个对象的引用,而不是对象本身,对象本身存放在该引用值所表示的地址的位置,包含:数组、类、接口,需要的朋友可以参考下
    2023-11-11
  • Spring boot如何开启跨域配置

    Spring boot如何开启跨域配置

    这篇文章主要介绍了Spring boot如何开启跨域配置问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-08-08
  • JDBC获取数据库连接由浅入深

    JDBC获取数据库连接由浅入深

    大家好,本篇文章主要讲的是JDBC获取数据库连接由浅入深,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下
    2022-02-02
  • mybatis 查询方式与效率高低对比

    mybatis 查询方式与效率高低对比

    这篇文章主要介绍了mybatis 查询方式与效率高低对比,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-03-03
  • Spring Boot中配置定时任务、线程池与多线程池执行的方法

    Spring Boot中配置定时任务、线程池与多线程池执行的方法

    这篇文章主要给大家介绍了关于Spring Boot中配置定时任务、线程池与多线程池执行的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用Spring Boot具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-09-09

最新评论