文件上传、下载、合并、分片、删除
使用了Hutool工具类库
Controller层
除了 MultipartFile
其他参数可以忽视
/**
* 前端上传文件
*
* @param file
* @param proxyId
* @return
* @throws IOException
*/
@PostMapping("/upload")
public Result<Void> fileUpload(@RequestParam("file")MultipartFile file,
String proxyId) throws IOException {
fileListService.upload(file, proxyId);
return Result.success();
}
/**
* 前端下载文件
*
* @param proxyId
* @param name
* @return
* @throws IOException
*/
@GetMapping("/download")
public Result<String> download(@RequestParam("proxyId") String proxyId,
@RequestParam("name") String name, String size, HttpServletResponse response)
throws IOException {
return fileListService.download(proxyId, name, size, response) ? Result.success("下载成功")
: Result.failed("下载失败,请检查文件目录");
}
Service层
上传文件
public void upload(MultipartFile multipartFile, String proxyId) throws IOException {
//文件夹路径
String folder = MqttConstants.FILE_PATH_OUTPUT + "/" + proxyId;
File dist = new File(folder);
if (!dist.isDirectory()) {
//文件夹不存在 --> 创建文件夹
dist.mkdirs();
}
//文件夹 + 文件名(带后缀)
File file = new File(folder + "/" + multipartFile.getOriginalFilename());
multipartFile.transferTo(file);
}
下载文件,这里包含了已分片文件合并成整个文件和删除文件操作
// 下载文件 --> 去OUTPUT目录查看是否有这个文件
// 无 --> 去INPUT目录查找目录,将文件分片合并成一个文件,到OUTPUT目录,并删除INPUT目录下的分片文件
// 有 --> 去OUTPUT目录下载文件
public boolean download(String proxyId, String name, String size, HttpServletResponse response)
throws IOException {
//1、判断是否存在这个文件
// output/proxyId/name
File folder = new File(MqttConstants.FILE_PATH_OUTPUT + "/" + proxyId + "/" + name);
log.info("去目录判断是否存在:" + MqttConstants.FILE_PATH_OUTPUT + "/" + proxyId + "/" + name);
//文件不存在 去合并文件
if (!folder.exists()) {
log.info(
"文件不存在,去合并文件,合并目录内的文件:" + MqttConstants.FILE_PATH_INPUT + "/" + proxyId + "/" + name
+ "/");
File input = new File(MqttConstants.FILE_PATH_INPUT + "/" + proxyId + "/" + name + "/");
if (!input.exists()) {
log.info("=============合并目录不存在=============");
return false;
} else {
FilterByText filter = new FilterByText(name);
String[] list = input.list(filter);
assert list != null;
byte[] bytes = new byte[Integer.parseInt(size)];
int length = list.length;
System.out.println("文件个数:" + length);
BufferedOutputStream bufferedOutput = null;
if (list.length != 0) {
int count = 0;
TimeInterval timer = DateUtil.timer();
for (String str : list) {
//#& --> 接收文件分片后重新命名文件,作为标识符的
int i = Integer.parseInt(str.split("#&")[0]);
File file = new File(input + "/" + str);
count++;
FileReader reader = new FileReader(file);
byte[] bb = reader.readBytes();
System.arraycopy(bb, 0, bytes, (i - 1) * 2, bb.length);
File outFile = new File(MqttConstants.FILE_PATH_OUTPUT + "/" + proxyId);
if (!outFile.exists()) {
outFile.mkdirs();
}
File out = new File(MqttConstants.FILE_PATH_OUTPUT + "/" + proxyId + "/" + name);
OutputStream output = new FileOutputStream(out);
bufferedOutput = new BufferedOutputStream(output);
bufferedOutput.write(bytes);
}
bufferedOutput.close();
log.info("文件总个数:" + length + "个,合并了" + count + "个文件,共耗时" + timer.intervalSecond() + "秒");
}
//删除文件目录以及目录内容
deleteDir(input);
}
}
response.setHeader("Content-disposition", "attachment;filename=" + name);
//拿到需要下载的文件
File file = new File(MqttConstants.FILE_PATH_OUTPUT + "/" + proxyId + "/" + name);
//file转byte[]
FileReader reader = new FileReader(file);
byte[] bb = reader.readBytes();
//文件大小
response.addHeader("Content-Length", "" + file.length());
ServletOutputStream outputStream = response.getOutputStream();
outputStream.write(bb);
outputStream.close();
return true;
}
/**
* 递归删除目录下的所有文件及子目录下所有文件
*
* @param dir 将要删除的文件目录
* @return boolean Returns "true" if all deletions were successful. If a deletion fails, the
* method stops attempting to delete and returns "false".
*/
private static boolean deleteDir(File dir) {
if (dir.isDirectory()) {
String[] children = dir.list();
//递归删除目录中的子目录下
for (int i = 0; i < children.length; i++) {
boolean success = deleteDir(new File(dir, children[i]));
if (!success) {
return false;
}
}
}
// 目录此时为空,可以删除
return dir.delete();
}
文件分片 这里将文件分片后 转成Base64通过MQTT发了出去
public Boolean setFile(String proxyId, String name)
throws IOException, InterruptedException {
String folder = MqttConstants.FILE_PATH_OUTPUT + "/" + proxyId;
File dist = new File(folder);
if (!dist.isDirectory()) {
return false;
}
//读取文件
File file = new File(folder + "/" + name);
FileReader reader = new FileReader(file);
BufferedInputStream inputStream = reader.getInputStream();
//file转byte[]
byte[] bytes = reader.readBytes();
int length = bytes.length;
//这里是具体的业务逻辑了 可以忽视
MqttMsg mqttMsg = new MqttMsg();
mqttMsg.setServiceId(proxyId);
mqttMsg.setClientId(MqttConstants.EMP);
mqttMsg.setDirection(MqttConstants.DIRECTION_REQUEST);
mqttMsg.setVersion(MqttConstants.VERSION_V1);
mqttMsg.setDeviceId("xx");
mqttMsg.setMId("xx");
mqttMsg.setTimestamp("xx");
mqttMsg.setExpire("xx");
mqttMsg.setType(TopicType.SET_FILE);
//字节小于10KB 不需要分片
//这里可以根据自己的分片需要定义
if (bytes.length < 10240) {
JSONObject object = new JSONObject();
object.put("name", name);
object.put("total", "1");
object.put("size", String.valueOf(length));
object.put("current", "1");
//Base64转换
String base64 = Base64.getEncoder().encodeToString(bytes);
object.put("data", base64);
mqttMsg.setParams(object);
mqttPublishService.publishRequest(mqttMsg, MqttConstants.QOS_1);
} else {
//字节大于 10KB 情况1整除 情况2非整除,有余数
int yu = length % 10240;
int split = length / 10240;
byte[] bb = new byte[10240];
//非整除,有余数 最后一片小于10KB 需特殊处理
if (yu != 0) {
for (int i = 0; i < split + 1; i++) {
//最后一片 特殊处理
if (i == split) {
bb = new byte[i];
inputStream.read(bb, 0, i);
} else {
//每片 10KB
inputStream.read(bb, 0, 10240);
}
String base64 = Base64.getEncoder().encodeToString(bb);
JSONObject object = new JSONObject();
object.put("name", name);
object.put("total", String.valueOf(split));
object.put("size", String.valueOf(length));
object.put("current", String.valueOf(i));
object.put("data", base64);
mqttMsg.setParams(object);
mqttPublishService.publishRequest(mqttMsg, MqttConstants.QOS_1);
//避免丢包 延时2ms
Thread.sleep(2);
}
} else {
//整除
for (int i = 0; i < split; i++) {
inputStream.read(bb, 0, 10240);
String base64 = Base64.getEncoder().encodeToString(bb);
JSONObject object = new JSONObject();
object.put("name", name);
object.put("total", String.valueOf(split));
object.put("size", String.valueOf(length));
object.put("current", String.valueOf(i));
object.put("data", base64);
mqttMsg.setParams(object);
mqttPublishService.publishRequest(mqttMsg, MqttConstants.QOS_1);
//避免丢包 延时2ms
Thread.sleep(2);
}
}
}
return true;
}