Java实现单文件上传、文件预览(流的方式)、单文件下载 功能实例详解

本文详细介绍了如何在SpringBoot中实现单文件上传、文件预览(流方式)和单文件下载功能。针对文件上传时超过大小限制的问题,提供了两种解决方案:修改application配置或在启动类添加代码。文件预览支持图片和视频,但不支持docx文件。文件下载通过设置相应头实现。文章还展示了Service、ServiceImpl、Mapper和Mapper.xml的相关代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这篇文章主要介绍了Java中的单文件上传、文件预览(流的方式)、单文件下载功能的实现,在开发中,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下


1 :MySql数据库:

1.1 :sftp_file 数据

在这里插入图片描述

1.2:sftp_file 表结构执行创建语句

CREATE TABLE `sftp_file` (
  `file_id` varchar(100) COLLATE utf8mb4_bin NOT NULL COMMENT '文件id',
  `file_name_up` varchar(300) COLLATE utf8mb4_bin NOT NULL COMMENT '文件名称',
  `file_name` varchar(300) COLLATE utf8mb4_bin NOT NULL COMMENT '上传文件名称',
  `file_type` varchar(20) COLLATE utf8mb4_bin NOT NULL COMMENT '文件类型',
  `file_size` varchar(30) COLLATE utf8mb4_bin DEFAULT NULL COMMENT '文件大小 单位:B',
  `server_ip` varchar(300) COLLATE utf8mb4_bin DEFAULT NULL COMMENT '文件服务器地址',
  `file_path` varchar(300) COLLATE utf8mb4_bin NOT NULL COMMENT '文件上传路径',
  `user_id` varchar(50) COLLATE utf8mb4_bin NOT NULL COMMENT '操作用户id',
  `create_time` datetime NOT NULL COMMENT '上传日期',
  PRIMARY KEY (`file_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='附件表';

2 :Controller 单文件上传、文件预览(流的方式)、单文件下载(所有的业务我在Controller 处理的、为了方便大家更直观的阅读代码)

2.1:单文件上传

代码如下(示例):

import com.jeewechat.wechat.entity.SftpFile;
import com.jeewechat.wechat.service.FileService;
import io.swagger.annotations.Api;
import lombok.extern.log4j.Log4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.math.BigDecimal;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Date;

@Api(value = "FileController", tags = {"文件(附件)信息表"})
@Log4j
@Controller
@RequestMapping("/file")
public class FileController {

    @Autowired
    private FileService fileService;

    /**
     * @param userId 用户ID
     * @param file   文件对象
     * @return java.lang.String
     * @description TODO 单文件上传
     * @author WangTianLiang
     * @date 2021/5/19
     */
    @ApiOperation("单文件上传")
    @RequestMapping(value = "uploadFile", method = RequestMethod.POST)
    @ResponseBody
    public String uploadFile(@RequestParam("file") MultipartFile file, @RequestParam("userId") String userId) {
        //step 1: 封装实例对象
        SftpFile sftpFile = new SftpFile();
        String fileId = SftpFile.createDbId();//随机生产主键ID
        sftpFile.setFileId(fileId);//文件id
        sftpFile.setUserId(userId);//操作用户id
        sftpFile.setCreateTime(new Date());//创建时间

        // 获取原始名字
        String fileNameUp = file.getOriginalFilename();
        sftpFile.setFileNameUp(fileNameUp);//上传文件名称

        sftpFile.setFileName(fileId);//存储文件的名称

        // 获取后缀名
        String suffixType = fileNameUp.substring(fileNameUp.lastIndexOf(".") + 1);
        sftpFile.setFileType(suffixType);//文件类型

        //获得文件大小
        Float size = Float.parseFloat(String.valueOf(file.getSize())) / 1024;
        BigDecimal b = new BigDecimal(size);
        size = b.setScale(2, BigDecimal.ROUND_HALF_UP).floatValue();
        sftpFile.setFileSize(size.toString());//文件大小(字节单位)

        // 文件保存路径
        String filePath = "E://image//";
        sftpFile.setFilePath(filePath);//文件上传路径

        // 文件重命名,防止重复
        String filePathName = filePath + fileId + "." + sftpFile.getFileType();
        //本机ip 静态方法获取InetAddress对象。
        InetAddress ia = null;
        try {
            ia = ia.getLocalHost();// 获取本地主机
            sftpFile.setServerIp(ia.getHostAddress());
        } catch (UnknownHostException e) {
            log.error("文件传输服务器失败:", e);
        }
        //step 2: 创建文件对象
        File dest = new File(filePathName);
        //step 3: 判断路径是否存在,如果不存在则创建
        if (!dest.getParentFile().exists()) {
            dest.getParentFile().mkdirs();
        }

        //文件存在,返回
        if (dest.exists()) {
            return "文件已存在";
        }
        try {
            //step 4: 保存到服务器中
            file.transferTo(dest);
            int i = fileService.insertFile(sftpFile);
            //step 5: 判断文件对象不为空
            if (i > 0) {
                 return "文件上传成功:"+fileId;
            }
        } catch (Exception e) {
            log.error("文件传输服务器失败:", e);
        }
        return "文件上传失败";
    }
}
2.1.1:单文件上传结果

在这里插入图片描述

2.1.2:文件上传遇到的 The field file exceeds its maximum permitted size of 1048576 bytes.

在这里插入图片描述

SpringBoot文件上传时出现了The field file exceeds its maximum permitted size of 1048576 bytes.错误,显示文件的大小超出了允许的范围。查看了官方文档,原来Spring Boot工程嵌入的tomcat限制了请求的文件大小。
原因:每个文件的配置最大为1Mb,单次请求的文件的总数不能大于10Mb。要更改这个默认值需要在配置文件(如application.properties)中加入两个配置

2.1.2.1:解决方案一 (根据spring boot 版本不同在application文件添加不同的配置)
#Spring Boot 1.3.x或者之前

#设置单个文件的大小
multipart.maxFileSize=10Mb
#设置单次请求的文件的总大小
multipart.maxRequestSize=1000Mb
 
#Spring Boot 1.4.x

#设置单个文件的大小
spring.http.multipart.maxFileSize=10Mb
#设置单次请求的文件的总大小
spring.http.multipart.maxRequestSize=1000Mb
 
#Spring Boot 2.0之后

#设置单个文件的大小
spring.servlet.multipart.max-file-size=10Mb
#设置单次请求的文件的总大小
spring.servlet.multipart.max-request-size=1000Mb

我在项目中采用配置的是Spring Boot 2.0之后(示图):
在这里插入图片描述

2.1.2.2:解决方案二 (在启动类添加如下代码)
    /**
     * @return javax.servlet.MultipartConfigElement
     * @description TODO 设置上传文件的大小
     * @author WangTianLiang
     * @date 2021/5/21
     */
    @Bean
    public MultipartConfigElement multipartConfigElement() {
        MultipartConfigFactory factory = new MultipartConfigFactory();
        //单个文件最大
        factory.setMaxFileSize(DataSize.parse("10240KB")); //KB,MB
        // 设置总上传数据总大小
        factory.setMaxRequestSize(DataSize.parse("102400KB"));
        return factory.createMultipartConfig();
    }

我在项目中运用(示例):
在这里插入图片描述

2.2:文件预览(流的方式)

代码如下(示例):

import com.jeewechat.wechat.entity.SftpFile;
import com.jeewechat.wechat.service.FileService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.log4j.Log4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.OutputStream;
import java.io.RandomAccessFile;

@Api(value = "FileController", tags = {"文件(附件)信息表"})
@Log4j
@Controller
@RequestMapping("/file")
public class FileController {

    @Autowired
    private FileService fileService;

    /**
     * @param fileId   文件ID
     * @param response
     * @param request
     * @return void 返回文件数据
     * @description TODO 流的方式预览文件
     * @author WangTianLiang
     * @date 2021/5/18
     */
    @ApiOperation("文件预览")
    @ApiImplicitParams({@ApiImplicitParam(name = "fileId", value = "文件对应id", required = true, dataType = "String")})
    //@CrossOrigin(origins = "*", maxAge = 3600)//解决跨域问题  origins:是允许访问的列表(origins=“网址”) maxAge:准备响应前的 缓存持续的 最大时间
    @RequestMapping(value = "viewFile", method = RequestMethod.GET)
    public void viewFile(@RequestParam("fileId") String fileId, HttpServletResponse response, HttpServletRequest request) throws Exception {
        //step 1: 根据 fileId(文件ID)查询 文件详情信息
        SftpFile sftpFile = fileService.selectByPrimaryKey(fileId);
        if (sftpFile == null) {
            return;
        }
        String filePath = sftpFile.getFilePath();//文件上传路径 例如:E:\image
        String fileName = sftpFile.getFileName();//上传文件名称 例如:学习资料
        String fileType = sftpFile.getFileType();//文件类型 例如:docx
        StringBuffer stringBuffer = new StringBuffer(); //创建StringBuffer 用于拼接文件路径 E://image//学习资料.docx
        StringBuffer appendFilePath = stringBuffer.append(filePath).append("//").append(fileName).append(".").append(fileType);
        //step 2: 文件地址,真实环境是存放在数据库中的
        File file = new File(appendFilePath.toString());
        //step 3: 创建输入对象
        FileInputStream fis = new FileInputStream(file);
        //输出字符流数据或者二进制的字节流数据
        OutputStream os = response.getOutputStream();
        //step 4: 判断校验文件格式,并设置相关文件格式
        if ("jpg,jepg,gif,png,bmp".contains(fileType)) {//图片类型
            response.setContentType("image/" + fileType);//设置文件类型参数
        }
        //设置视频
        if ("mp4".contains(fileType)) {
            //开始视频预览
            RandomAccessFile targetFile = new RandomAccessFile(file, "r");
            //获取从那个字节开始读取文件
            String rangeString = request.getHeader("Range");
            rangeString = "bytes=0-0";
            long fileLength = targetFile.length();
            //播放
            if (rangeString != null) {
                long range = Long.valueOf(rangeString.substring(rangeString.indexOf("=") + 1, rangeString.indexOf("-")));
                //设置内容类型
                response.setHeader("Content-Type", "video/" + fileType);
                //设置此次相应返回的数据长度
                response.setHeader("Content-Length", String.valueOf(fileLength - range));
                //设置此次相应返回的数据范围
                response.setHeader("Content-Range", "bytes " + range + "-" + (fileLength - 1) + "/" + fileLength);
                //返回码需要为206,而不是200
                response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
                //设定文件读取开始位置(以字节为单位)
                targetFile.seek(range);
            }
        }
        // 创建字节数组
        byte[] buf = new byte[1024];
        int len = 0;
        while ((len = fis.read(buf)) != -1) {
            os.write(buf, 0, len);
        }
        //关闭流
        fis.close();
        os.close();
    }

}
2.2.1:文件预览结果

注:文件预览不支持 docx(文档格式),docx 格式预览需要转成 pdf,图片文件、视频文件都支持预览。
在这里插入图片描述

2.3:单文件下载

代码如下(示例):

import com.jeewechat.wechat.entity.SftpFile;
import com.jeewechat.wechat.service.FileService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import lombok.extern.log4j.Log4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.OutputStream;

@Api(value = "FileController", tags = {"文件(附件)信息表"})
@Log4j
@Controller
@RequestMapping("/file")
public class FileController {
    @Autowired
    private FileService fileService;

    /**
     * @param fileId
     * @param response
     * @return void
     * @description TODO 单文件下载
     * @author WangTianLiang
     * @date 2021/5/20
     */
    @ApiOperation("单文件下载")
    @RequestMapping(value = "downloadFile", method = RequestMethod.GET)
    @ApiImplicitParams({@ApiImplicitParam(name = "fileId", value = "文件对应id", required = true, dataType = "String")})
    public void downloadFile(@RequestParam("fileId") String fileId, HttpServletResponse response) throws Exception {
        //step 1: 根据 fileId(文件ID)查询 文件详情信息
        SftpFile sftpFile = fileService.selectByPrimaryKey(fileId);
        if (sftpFile == null) {
            return;
        }
        //创建StringBuilder用于拼接文件路径
        StringBuilder stringBuilder = new StringBuilder();
        //step 2: 获得文件真实路径
        StringBuilder filePath = stringBuilder.append(sftpFile.getFilePath()).append(sftpFile.getFileName()).append(".").append(sftpFile.getFileType());

        //step 3: 文件地址,真实环境是存放在数据库中的
        File file = new File(filePath.toString());
        //step 4: 创建输入对象
        FileInputStream fis = new FileInputStream(file);

        //step 5: 设置相关格式
        response.setContentType("application/force-download");
        // 设置下载后的文件名以及header
        response.addHeader("Content-disposition", "attachment;fileName=" + java.net.URLEncoder.encode(sftpFile.getFileNameUp(), "UTF-8"));
        // 创建输出对象
        OutputStream os = response.getOutputStream();
        // 创建字节数组
        byte[] buf = new byte[1024];
        int len = 0;
        while ((len = fis.read(buf)) != -1) {
            os.write(buf, 0, len);
        }
        //关闭流
        fis.close();
    }
}

2.3.1:单文件下载结果

在这里插入图片描述

3 :其它附属代码 Service,ServiceImpl,Mapper,Mapper.xml 代码如下

项目大致结构如下(如图示例):
在这里插入图片描述

3.1:Service:

代码如下(示例):

package com.jeewechat.wechat.service;

import com.jeewechat.wechat.entity.SftpFile;

public interface FileService {
    SftpFile selectByPrimaryKey(String fileId);

    int insertFile(SftpFile sftpFile);
}

3.2:ServiceImpl:

代码如下(示例):

package com.jeewechat.wechat.service.impl;

import com.jeewechat.wechat.entity.SftpFile;
import com.jeewechat.wechat.mapper.FileMapper;
import com.jeewechat.wechat.service.FileService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Slf4j
@Service
public class FileServiceImpl implements FileService {
    @Autowired
    private FileMapper fileMapper;

    @Override
    public SftpFile selectByPrimaryKey(String fileId) {
        return fileMapper.selectByPrimaryKey(fileId);
    }

    @Override
    public int insertFile(SftpFile sftpFile) {
        return fileMapper.insertFile(sftpFile);
    }

}

3.3:Mapper:

代码如下(示例):

package com.jeewechat.wechat.mapper;

import com.jeewechat.wechat.entity.SftpFile;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface FileMapper {
    int insertFile(SftpFile sftpFile);

    SftpFile selectByPrimaryKey(String fileId);
}

3.4 :Mapper.xml:

代码如下(示例):

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.jeewechat.wechat.mapper.FileMapper">
    <resultMap id="BaseResultMap" type="com.jeewechat.wechat.entity.SftpFile">
        <id column="file_id" property="fileId" jdbcType="VARCHAR"/>
        <result column="file_name_up" property="fileNameUp" jdbcType="VARCHAR"/>
        <result column="file_name" property="fileName" jdbcType="VARCHAR"/>
        <result column="file_type" property="fileType" jdbcType="VARCHAR"/>
        <result column="file_size" property="fileSize" jdbcType="VARCHAR"/>
        <result column="server_ip" property="serverIp" jdbcType="VARCHAR"/>
        <result column="file_path" property="filePath" jdbcType="VARCHAR"/>
        <result column="user_id" property="userId" jdbcType="VARCHAR"/>
        <result column="create_time" property="createTime" jdbcType="TIMESTAMP"/>
    </resultMap>
    
    <!-- 新增附件表 -->
    <insert id="insertFile" parameterType="com.jeewechat.wechat.entity.SftpFile">
        insert into sftp_file
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="fileId != null">
                file_id,
            </if>
            <if test="fileNameUp != null">
                file_name_up,
            </if>
            <if test="fileName != null">
                file_name,
            </if>
            <if test="fileType != null">
                file_type,
            </if>
            <if test="fileSize != null">
                file_size,
            </if>
            <if test="serverIp != null">
                server_ip,
            </if>
            <if test="filePath != null">
                file_path,
            </if>
            <if test="userId != null">
                user_id,
            </if>
            <if test="createTime != null">
                create_time,
            </if>
        </trim>
        <trim prefix="values (" suffix=")" suffixOverrides=",">
            <if test="fileId != null">
                #{fileId,jdbcType=VARCHAR},
            </if>
            <if test="fileNameUp != null">
                #{fileNameUp,jdbcType=VARCHAR},
            </if>
            <if test="fileName != null">
                #{fileName,jdbcType=VARCHAR},
            </if>
            <if test="fileType != null">
                #{fileType,jdbcType=VARCHAR},
            </if>
            <if test="fileSize != null">
                #{fileSize,jdbcType=VARCHAR},
            </if>
            <if test="serverIp != null">
                #{serverIp,jdbcType=VARCHAR},
            </if>
            <if test="filePath != null">
                #{filePath,jdbcType=VARCHAR},
            </if>
            <if test="userId != null">
                #{userId,jdbcType=DECIMAL},
            </if>
            <if test="createTime != null">
                NOW(),
            </if>
        </trim>
    </insert>
    
    <!-- 根据主键fileId(文件ID)查询附件表 -->
    <select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.String">
        select
        *
        from sftp_file
        where file_id = #{fileId,jdbcType=VARCHAR}
    </select>

</mapper>

希望可以帮助到您…

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值