一丶需求
移动端根据文件流进行选择地址下载文件, 每次下载文件路径都会不同, 避免可根据地址重复下载或泄露文件.
二丶具体实现(直接上代码)
1丶编写接口(get请求)
@GetMapping("/getPdfFile")
@ApiOperation(value = "公众号拿取报告pdf接口")
public AjaxResult getPdfFile(@RequestParam("chid") Integer chid, HttpServletResponse response) {
return iMedicalAppointmentService.getCheckReportbyFile(chid, response);
}
2丶连接FTP服务获取文件
/**
* @param filePath 文件相对路径
* @param response 响应对象
*/
public static void getPdfFileStream(String filePath, HttpServletResponse response) {
FtpUtil ftpUtil = BeanHelper.getBean(FtpUtil.class);
FTPClient ftpClient = ftpUtil.getFtpClient(3);
ftpUtil.downFileStream(ftpClient, filePath, response);
}
3丶将文件流写入响应对象
/**
* 文件流传输
*
* @param ftpClient FTP
* @param fileName
* @param response
*/
public void downFileStream(FTPClient ftpClient, String fileName, HttpServletResponse response) {
InputStream inputStream = null;
OutputStream outputStream = null;
try {
// 设置文本类型
response.setContentType(String.valueOf(MediaType.APPLICATION_OCTET_STREAM));
// 设置文件类型和文件名
response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + new Date().getTime() + ".pdf");
outputStream = new BufferedOutputStream(response.getOutputStream());
ftpClient.enterLocalPassiveMode();
// 获取ftp上的文件流
inputStream = ftpClient.retrieveFileStream(fileName);
// 文件流写入
int len;
byte[] bytes = new byte[1024];
while ((len = inputStream.read(bytes)) != -1) {
outputStream.write(bytes, 0, len);
}
}catch (Exception e) {
log.error("FTP file download failed!" + e.getMessage());
} finally {
try {
if (inputStream != null) {
inputStream.close();
}
// 强制将缓存区的数据进行输出
assert outputStream != null;
outputStream.flush();
// 关流
outputStream.close();
} catch (IOException e) {
log.error("Download stream failed to close" + e.getMessage());
}
}
}
FTP连接方法如下:
/**
* @param type 1-B超 2-心电图 3后续再加 3-36服务器
* @author LingCoder
* @date 2020/10/21 12:24
* @description: 根据传进来的ftp类型,初始化对应ftp服务器
*/
public FTPClient getFtpClient(Integer type) {
FTPClient ftpClient = new FTPClient();
ftpClient.setControlEncoding("utf-8");
FtpConnect ftpConnect = new FtpConnect();
switch (type) {
// B超
case 1:
log.info("connecting...ftp server:" + BCHostName + ":" + BCPort);
ftpConnect.setHostname(BCHostName);
ftpConnect.setPort(BCPort);
ftpConnect.setUsername(BCUsername);
ftpConnect.setPassword(BCPassword);
break;
// 心电图
case 2:
log.info("connecting...ftp server:" + XDTHostName + ":" + XDTPort);
ftpConnect.setHostname(XDTHostName);
ftpConnect.setPort(XDTPort);
ftpConnect.setUsername(XDTUsername);
ftpConnect.setPassword(XDTPassword);
break;
case 3:
log.info("connecting...ftp server:" + HostName36 + ":" + Port36);
ftpConnect.setHostname(HostName36);
ftpConnect.setPort(Port36);
ftpConnect.setUsername(Username36);
ftpConnect.setPassword(Password36);
break;
case 4:
log.info("connecting...ftp server:" + HostName51 + ":" + Port51);
ftpConnect.setHostname(HostName51);
ftpConnect.setPort(Port51);
ftpConnect.setUsername(Username51);
ftpConnect.setPassword(Password51);
break;
default:
log.info("No ftp server has been matched yet");
break;
}
try {
//设置连接超时时间
ftpClient.setDataTimeout(1000 * 120);
// 连接ftp服务器
ftpClient.connect(ftpConnect.getHostname(), ftpConnect.getPort());
// 登录ftp服务器
ftpClient.login(ftpConnect.getUsername(), ftpConnect.getPassword());
// 中文支持
ftpClient.setControlEncoding("UTF-8");
// 设置文件类型为二进制(如果从FTP下载或上传的文件是压缩文件的时候,不进行该设置可能会导致获取的压缩文件解压失败)
ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
//开启被动模式,否则文件上传不成功,也不报错
ftpClient.enterLocalPassiveMode();
// 是否成功登录服务器
int replyCode = ftpClient.getReplyCode();
// 开启服务器对UTF-8的支持,如果服务器支持就用UTF-8编码,否则就使用本地编码(GBK).
if (FTPReply.isPositiveCompletion(ftpClient.sendCommand(
"OPTS UTF8", "ON"))) {
LOCAL_CHARSET = "UTF-8";
}
if (!FTPReply.isPositiveCompletion(replyCode)) {
ftpClient.disconnect();
throw new FtpConnectException("connect failed...ftp server:" + ftpConnect.getHostname() + ":" + ftpConnect.getPort());
}
log.info("connect successfu...ftp server:" + ftpConnect.getHostname() + ":" + ftpConnect.getPort());
} catch (Exception e) {
log.error(e.getMessage(), e);
}
return ftpClient;
}