这篇文章主要介绍了Java中的文件批量上传、文件批量下载功能的实现,在开发中,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
文章目录
- 1 :MySql数据库:
- 1.1 :sftp_file 数据
- 1.2:sftp_file 表结构执行创建语句
- 2 :Controller 批量上传、批量下载 (所有的业务我在Controller 处理的、为了方便大家更直观的阅读代码)
- 2.1:批量上传文件
- 2.1.1:批量上传文件结果
- 2.1.2:spring boot 项目中 appConfig.properties 中加入两个配置参数
- 2.2:批量下载文件
- 2.2.1:批量下载文件结果
- 3 :其它附属代码 Mapper,Mapper.xml 代码如下
- 3.1:Mapper:
- 3.2 :Mapper.xml:
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.mapper.FileMapper;
import io.swagger.annotations.Api;
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 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.*;
@Api(value = "BatchFilesController", tags = {"文件(附件)信息表"})
@Log4j
@Controller
@RequestMapping("/batchFiles")
public class BatchFilesController {
@Autowired
private FileMapper fileMapper;
/**
* @param userId 用户ID
* @param files 文件对象
* @return java.lang.String
* @description TODO 批量文件上传
* @author WangTianLiang
* @date 2021/5/21
*/
@ApiOperation("批量文件上传")
@RequestMapping(value = "batchUploadFile", method = RequestMethod.POST)
@ResponseBody
public Map<String, Object> batchUploadFile(@RequestParam("files") MultipartFile[] files, @RequestParam("userId") String userId) {
Map<String, Object> mapData = new HashMap<>();
//step 1: 判断校验文件流是否有文件
if (files == null || files.length <= 0) {
mapData.put("success", false);//false:成功,false:失败
mapData.put("msg", "系统未检测到文件流");
return mapData;
}
//step 2: 创建List集合用于存储文件对象
List<SftpFile> sftpFileList = new ArrayList<>();
//step 3: 创建List集合用于存储文件ID,返给前端
List<String> sftpFileIdList = new ArrayList<>();
for (MultipartFile file : files) {
//step 4: 封装实例对象
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());//文件大小(字节单位)
// 文件保存路径 你还可以在拼接一层路径,例如 20210521 每天上传的都会生成一个新的文件加里
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 5: 创建文件对象
File dest = new File(filePathName);
//step 6: 判断路径是否存在,如果不存在则创建
if (!dest.getParentFile().exists()) {
dest.getParentFile().mkdirs();
}
//step 7: 文件存在,返回
if (dest.exists()) {
mapData.put("success", false);//false:成功,false:失败
mapData.put("msg", "文件已存在,请重新上传" + fileNameUp);
return mapData;
}
try {
//step 8: 保存到服务器中
file.transferTo(dest);
//step 9: 将生产的文件ID 和文件对象分别存入对应的集合
sftpFileIdList.add(fileId);
sftpFileList.add(sftpFile);
} catch (Exception e) {
log.error("文件传输服务器失败:", e);
}
}
//判断校验存储文件对象集合是否为空、集合长度是否大于0
if (sftpFileList != null && sftpFileList.size() > 0) {
//step 10: 批量添加文件对象
int i = fileMapper.batchInsertFile(sftpFileList);
//step 11: 判断是否添加成功 存储文件对象的集合长度是否等于数据库执行的条数
if (sftpFileList.size() == i) {
mapData.put("success", true);//false:成功,false:失败
mapData.put("msg", "文件上传成功");
mapData.put("data", sftpFileIdList);
return mapData;
}
}
mapData.put("success", false);//false:成功,false:失败
mapData.put("msg", "文件上传失败");
return mapData;
}
}
2.1.1:批量上传文件结果
2.1.2:spring boot 项目中 appConfig.properties 中加入两个配置参数
配置如下(示例):
#设置单个文件的大小
spring.servlet.multipart.max-file-size=10Mb
#设置单次请求的文件的总大小
spring.servlet.multipart.max-request-size=1000Mb
我在项目中采用配置的是Spring Boot 2.0之后(示图):
2.2:批量下载文件
代码如下(示例):
import com.jeewechat.wechat.entity.SftpFile;
import com.jeewechat.wechat.mapper.FileMapper;
import io.swagger.annotations.Api;
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.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
@Api(value = "BatchFilesController", tags = {"文件(附件)信息表"})
@Log4j
@Controller
@RequestMapping("/batchFiles")
public class BatchFilesController {
@Autowired
private FileMapper fileMapper;
/**
* @param files 文件ID集合
* @param request 客户端请求对象
* @param response 服务器响应对象
* @return void
* @description TODO 批量下载文件
* @author WangTianLiang
* @date 2021/5/21
*/
@ApiOperation("批量下载文件")
@RequestMapping(value = "batchDownloadFile", method = RequestMethod.GET)
public void batchDownloadFile(@RequestBody List<String> files, HttpServletRequest request, HttpServletResponse response) {
//step 1: 判断校验参数信息是否为空
if (files == null || files.size() <= 0) {
return;
}
//step 2: 响应头的设置
response.reset();
response.setCharacterEncoding("utf-8");
response.setContentType("multipart/form-data");
//step 3: 设置压缩包的名字
String format = new SimpleDateFormat("yyyymmddhhmmsssss").format(new Date());//年+月+日+时+分+秒
String billname = "压缩文件-" + format;
String downloadName = billname + ".zip";
//step 4: 返回客户端浏览器的版本号、类型
String agent = request.getHeader("USER-AGENT");
try {
//step 5: 解决不同浏览器压缩包名字含有中文时乱码的问题
//针对IE或者以IE为内核的浏览器:
if (agent.contains("MSIE") || agent.contains("Trident")) {
downloadName = java.net.URLEncoder.encode(downloadName, "UTF-8");
} else {
//非IE浏览器的处理:
downloadName = new String(downloadName.getBytes("UTF-8"), "ISO-8859-1");
}
} catch (Exception e) {
log.error("中文时乱码的问题处理异常:", e);
}
response.setHeader("Content-Disposition", "attachment;fileName=\"" + downloadName + "\"");
//step 6: 设置压缩流:直接写入response,实现边压缩边下载
ZipOutputStream zipos = null;
try {
zipos = new ZipOutputStream(new BufferedOutputStream(response.getOutputStream()));
zipos.setMethod(ZipOutputStream.DEFLATED); //设置压缩方法
} catch (Exception e) {
e.printStackTrace();
}
//循环将文件写入压缩流
DataOutputStream os = null;
//step 7: 根据文件ID批量查询数据库获取文件信息
List<SftpFile> fileList = fileMapper.getFilesByIds(files);
if (fileList == null || fileList.size() <= 0) {
return;
}
//遍历文件信息(主要获取文件名/文件路径等)
for (SftpFile sftpFile : fileList) {
//文件路径 E://image// + 20210521125816942FILE00000000004 + . + PNG
//拼接后的路径 E://image//20210521125816942FILE00000000004.PNG
String filePath = sftpFile.getFilePath() + sftpFile.getFileName() + "." + sftpFile.getFileType();
//step 8: 创建文件对象
File file = new File(filePath);
if (!file.exists()) {
log.info("文件已不存在:" + sftpFile.getFileNameUp());
continue;
} else {
try {
//step 9: 添加ZipEntry,并ZipEntry中写入文件流
String fileName = sftpFile.getFileNameUp(); //测试图片.PNG
zipos.putNextEntry(new ZipEntry(fileName)); //在压缩文件中建立名字为 测试图片.PNG 的文件
os = new DataOutputStream(zipos); //创建输出对象
InputStream is = new FileInputStream(file);
byte[] b = new byte[100];
int length = 0;
while ((length = is.read(b)) != -1) {
os.write(b, 0, length);
}
is.close();
zipos.closeEntry();//方法关闭当前的ZIP条目并定位流以读取下一个条目
} catch (IOException e) {
log.error("ZipEntry写入文件流异常:", e);
}
}
}
try {
//清空缓冲区数据
os.flush();
//关闭流
os.close();
zipos.close();
} catch (IOException e) {
log.error("清空关闭流异常:", e);
}
}
}
2.2.1:批量下载文件结果
①批量下载,浏览器生成ZIP文件 如下(示图):
②ZIP文件中的图片文件 如下(示图):
3 :其它附属代码 Mapper,Mapper.xml 代码如下
项目大致结构如下(如图示例):
3.1:Mapper:
代码如下(示例):
import com.jeewechat.wechat.entity.SftpFile;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@Mapper
public interface FileMapper {
//批量添加文件对象
int batchInsertFile(@Param("sftpFileList") List<SftpFile> sftpFileList);
//根据文件ID批量查询文件信息
List<SftpFile> getFilesByIds(@Param("fileIdList") List<String> fileIdList);
}
3.2 :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">
<!--批量添加,附件表-->
<insert id="batchInsertFile" parameterType="java.util.List">
INSERT into sftp_file
(file_id,file_name_up,file_name,file_type,file_size,server_ip,file_path,user_id,create_time)
VALUES
<foreach item="item" collection="sftpFileList" index="index" separator=",">
(#{item.fileId,jdbcType=VARCHAR},
#{item.fileNameUp,jdbcType=VARCHAR},
#{item.fileName,jdbcType=VARCHAR},
#{item.fileType,jdbcType=VARCHAR},
#{item.fileSize,jdbcType=VARCHAR},
#{item.serverIp,jdbcType=VARCHAR},
#{item.filePath,jdbcType=VARCHAR},
#{item.userId,jdbcType=VARCHAR},
NOW())
</foreach>
</insert>
<!--根据文件ID批量查询文件信息-->
<select id="getFilesByIds" resultType="com.jeewechat.wechat.entity.SftpFile">
select
file_id as fileId,file_name_up as fileNameUp,file_name as fileName,
file_type as fileType,file_size as fileSize,server_ip as serverIp,
file_path as filePath,user_id asuserId,create_time as createTime
from sftp_file
where
<foreach collection="fileIdList" item="fileId" index="index" open=" file_id IN (" close=")" separator=",">
#{fileId,jdbcType=VARCHAR}
</foreach>
order by
CREATE_TIME DESC
</select>
</mapper>
希望可以帮助到您…