这篇文章主要介绍了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>
希望可以帮助到您…