1. Controller
- 使用hutool的ZipUtil根据文件夹路径打包成File对象
- 然后调用自定义的FileResponseUtil进行单线程数据传输
import cn.hutool.core.date.DateUtil;
import com.github.xiaoymin.knife4j.annotations.ApiSort;
import im.gy.zfile.core.util.FileResponseUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import cn.hutool.core.util.ZipUtil;import java.io.File;
import java.util.Date;// 给接口添加日志
@Api(tags = "日志")
// API在文档中的排序
@ApiSort(8)
@Slf4j
@RestController
@RequestMapping("/admin")
public class LogController {@Value("${zfile.log.path}")private String zfileLogPath;@GetMapping("/log/download")@ApiOperation(value = "下载系统日志")public ResponseEntity<Resource> downloadLog() {if (log.isDebugEnabled()) {log.debug("下载诊断日志");}File fileZip = ZipUtil.zip(zfileLogPath);String currentDate = DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss");return FileResponseUtil.exportSingThread(fileZip, "ZFile 诊断日志"+currentDate+".zip");}}
2. 文件传输具体实现代码
这里主要是基于二进制流实现的。
- 首先,在headers设置附件即文件名。
- 使用Hutool的FileUtil的getInputStream将file对象转换为BufferInputStream流。
- 将转换后的结果赋值给InputStreamResource。
- 需要注意的是需要设置Reponse响应体的返回数据格式,这里文件传输的格式是MediaType的APPLICATION_OCTET_STREAM格式。
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.InputStreamResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;import java.io.File;
import java.nio.charset.StandardCharsets;@Slf4j
public class FileResponseUtil {/*** 文件下载, 单线程, 不支持断点续传*/public static ResponseEntity<Resource> exportSingThread(File file, String fileName) {if (!file.exists()) {ByteArrayResource byteArrayResource = new ByteArrayResource("文件不存在或者异常,请联系管理员。".getBytes(StandardCharsets.UTF_8));return ResponseEntity.status(HttpStatus.NOT_FOUND).header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE).body(byteArrayResource);}MediaType mediaType = MediaType.APPLICATION_OCTET_STREAM;HttpHeaders headers = new HttpHeaders();if (StrUtil.isEmpty(fileName)) {fileName = file.getName();}headers.setContentDispositionFormData("attachment", StringUtils.encodeAllIgnoreSlashes(fileName));return ResponseEntity.ok().headers(headers).contentLength(file.length()).contentType(mediaType).body(new InputStreamResource(FileUtil.getInputStream(file)));}
}