Commit f4425203 authored by yexiong.wang's avatar yexiong.wang

fastDfs改文件服务器

parent bdf8b38f
...@@ -304,6 +304,13 @@ ...@@ -304,6 +304,13 @@
</exclusions> </exclusions>
</dependency> </dependency>
<!-- fastdfs end --> <!-- fastdfs end -->
<!-- sftp -->
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
<version>0.1.54</version>
</dependency>
</dependencies> </dependencies>
</project> </project>
package cn.quantgroup.customer.model.ftp;
import lombok.Data;
/**
* @author yexiong.wang
* @date 2022/02/27
*/
@Data
public class FileInfo {
private String fileName;
private byte[] fileBytes;
private String filePath;
public FileInfo(String fileName, byte[] fileBytes, String filePath) {
this.fileName = fileName;
this.fileBytes = fileBytes;
this.filePath = filePath;
}
}
package cn.quantgroup.customer.model.ftp;
import lombok.Builder;
import lombok.Data;
/**
* @author yexiong.wang
* @date 2022/02/27
*/
@Data
@Builder
public class ServerInfo {
private String username;
private String password;
private String host;
private String directory;
private int port;
}
package cn.quantgroup.customer.service.ftp;
import cn.quantgroup.customer.exception.BusinessException;
import cn.quantgroup.customer.model.ftp.FileInfo;
import cn.quantgroup.customer.model.ftp.ServerInfo;
import com.jcraft.jsch.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.Vector;
import static com.jcraft.jsch.ChannelSftp.SSH_FX_NO_SUCH_FILE;
@Slf4j
public class AbstractFtpService implements IFtpService {
private static final int SO_TIME_OUT = 60 * 1000; // 超时时间
private static final int TIME_OUT = 15 * 1000;
@Override
public Object send(Object request) {
return null;
}
@Override
public boolean send(FileInfo fileInfo, ServerInfo serverInfo, int retryTime) {
String path = fileInfo.getFilePath();
byte[] fileBytes = fileInfo.getFileBytes();
String fileName = fileInfo.getFileName();
if (StringUtils.isBlank(fileName)) {
throw new RuntimeException("文件名不能为空");
}
if (fileBytes == null) {
throw new RuntimeException("文件内容不能为空");
}
log.info("AbstractFtpService send fileName={}", fileName);
JSch jsch = null;
Session session = null;
Channel channel = null;
ChannelSftp channelSftp = null;
/**
* 方法返回值
*/
boolean result = Boolean.FALSE;
try {
jsch = new JSch();
session = jsch.getSession(serverInfo.getUsername(), serverInfo.getHost(), serverInfo.getPort());
session.setPassword(serverInfo.getPassword().getBytes(Charset.forName("ISO-8859-1")));
Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.setTimeout(SO_TIME_OUT);
log.info("连接SFTP服务器host={},port={}", serverInfo.getHost(), serverInfo.getPort());
session.connect(TIME_OUT);
channel = session.openChannel("sftp");
channel.connect();
channelSftp = (ChannelSftp)channel;
log.info("SFTPclient打开channel...");
InputStream input = null;
if (!session.isConnected() || !channelSftp.isConnected()) {
log.error("SFTPchannel已经关闭");
throw new BusinessException("SFTPchannel已经关闭");
}
// 目录不存在则创建
SftpATTRS exist = null;
try {
exist = channelSftp.lstat(serverInfo.getDirectory().concat(path));
} catch (SftpException e) {
log.info("路径不存在{},exist={}", serverInfo.getDirectory().concat(path),exist);
}
if (exist == null && StringUtils.isNotBlank(path)) {
path = serverInfo.getDirectory().concat(path);
createPath(path, channelSftp);
} else if (StringUtils.isBlank(path)) {
path = serverInfo.getDirectory();
} else {
path = serverInfo.getDirectory().concat(path);
}
log.info("SFTP.client.切换到目录={}", path);
channelSftp.cd(path);
log.info("SFTP.client.切换到目录成功={}", path);
input = new ByteArrayInputStream(fileBytes);
// 重试标上传志位
boolean retry = Boolean.TRUE;
int alreadyTryTime = 0;
log.info("开始上传文件");
// 发生异常,重试三次
while (retry && alreadyTryTime <= retryTime) {
try {
channelSftp.put(input, fileName);
log.info("SFTP.client.上传成功 目录={} 文件名={}", path, fileName);
result = Boolean.TRUE;
retry = Boolean.FALSE;
} catch (Exception e) {
log.error("SFTP文件上传失败 filename:{},alreadyTryTime:{},e:{}", fileName, alreadyTryTime, e);
try {
Thread.sleep(300);
} catch (InterruptedException interruptedException) {
}
alreadyTryTime++;
}
}
if (!result) {
throw new BusinessException("SFTP服务器异常!");
}
if (channelSftp != null) {
channelSftp.disconnect();
}
if (channel != null) {
channel.disconnect();
}
if (session != null) {
session.disconnect();
}
} catch (JSchException e) {
log.error("JSchException fileName={},e={}", fileName, ExceptionUtils.getStackTrace(e));
throw new BusinessException("SFTP创建连接失败, 信息="+ e);
} catch (SftpException e) {
log.error("SftpException fileName={},e={}", fileName, ExceptionUtils.getStackTrace(e));
throw new BusinessException("SFTP.client.操作失败");
}
return result;
}
protected void createPath(String path, ChannelSftp channelSftp) throws SftpException {
String[] folders = path.split("/");
for (String folder : folders) {
if (folder.length() > 0) {
try {
channelSftp.cd(folder);
} catch (SftpException e) {
try {
channelSftp.mkdir(folder);
} catch (SftpException e1) {
log.info("创建失败,path:{}, exception:{}", path, ExceptionUtils.getStackTrace(e1));
}
channelSftp.cd(folder);
}
}
}
}
@Override
public byte[] down(String fullName, ServerInfo serverInfo, int retryTime) throws Exception {
ByteArrayOutputStream fileOutputStream = new ByteArrayOutputStream();
JSch jsch;
Session session = null;
Channel channel = null;
ChannelSftp channelSftp = null;
try {
jsch = new JSch();
session = jsch.getSession(serverInfo.getUsername(), serverInfo.getHost(), serverInfo.getPort());
session.setPassword(serverInfo.getPassword().getBytes(Charset.forName("ISO-8859-1")));
Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.setTimeout(SO_TIME_OUT);
log.info("连接 SFTP 服务器 " + serverInfo.getHost() + ":" + serverInfo.getPort());
session.connect(TIME_OUT);
channel = session.openChannel("sftp");
channel.connect();
channelSftp = (ChannelSftp)channel;
log.info("SFTP client 打开 channel ...");
if (channelSftp == null || session == null || !session.isConnected() || !channelSftp.isConnected()) {
log.warn("SFTP channel 已经关闭");
throw new BusinessException("SFTP channel 已经关闭");
}
channelSftp.get(fullName, fileOutputStream);
byte[] data = fileOutputStream.toByteArray();
if (data == null || data.length < 2) {
log.warn("SFTP.client.下载回来的文件长度不对!文件名={}", fullName);
return null;
}
log.info("SFTP.client.下载成功 文件名={}", fullName);
return data;
} catch (JSchException e) {
log.warn("SFTP.client.创建连接失败");
throw new BusinessException("SFTP创建连接失败, 信息=" + e);
} catch (SftpException e) {
log.warn("SFTP.client.操作失败, 信息exception=", e);
if (e.id == SSH_FX_NO_SUCH_FILE) {
throw new FileNotFoundException("file not found " + fullName);
}
throw new BusinessException("SFTP.client.操作失败");
} finally {
if (channelSftp != null) {
channelSftp.disconnect();
}
if (channel != null) {
channel.disconnect();
}
if (session != null) {
session.disconnect();
}
}
}
@Override
public List<String> listDirectory(ServerInfo serverInfo) throws Exception {
JSch jsch;
Session session = null;
Channel channel = null;
ChannelSftp channelSftp = null;
try {
jsch = new JSch();
session = jsch.getSession(serverInfo.getUsername(), serverInfo.getHost(), serverInfo.getPort());
session.setPassword(serverInfo.getPassword().getBytes(Charset.forName("ISO-8859-1")));
Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.setTimeout(SO_TIME_OUT);
log.info("连接 SFTP 服务器 " + serverInfo.getHost() + ":" + serverInfo.getPort());
session.connect(TIME_OUT);
channel = session.openChannel("sftp");
channel.connect();
channelSftp = (ChannelSftp)channel;
log.info("SFTP client 打开 channel ...");
if (channelSftp == null || session == null || !session.isConnected() || !channelSftp.isConnected()) {
log.warn("SFTP channel 已经关闭");
throw new BusinessException("SFTP channel 已经关闭");
}
List<String> fileNameList = new ArrayList<>();
Vector<ChannelSftp.LsEntry> fileNameVector = channelSftp.ls(serverInfo.getDirectory());
for(ChannelSftp.LsEntry lsEntry : fileNameVector){
if(lsEntry.getFilename().equals(".") || lsEntry.getFilename().equals("..")){
continue;
}
fileNameList.add(lsEntry.getFilename());
}
return fileNameList;
} catch (JSchException e) {
log.warn("SFTP.client.创建连接失败");
throw new BusinessException("SFTP创建连接失败, 信息={}" + e);
} catch (SftpException e) {
log.warn("SFTP.client.操作失败, 信息exception=", e);
if (e.id == SSH_FX_NO_SUCH_FILE) {
throw new FileNotFoundException("directory not found " + serverInfo.getDirectory());
}
throw new BusinessException("SFTP.client.操作失败");
} finally {
if (channelSftp != null) {
channelSftp.disconnect();
}
if (channel != null) {
channel.disconnect();
}
if (session != null) {
session.disconnect();
}
}
}
}
package cn.quantgroup.customer.service.ftp;
import cn.quantgroup.customer.model.ftp.FileInfo;
import cn.quantgroup.customer.model.ftp.ServerInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.util.Map;
/**
* @author yexiong.wang
* @date 2022/02/27
*/
@Slf4j
@Service("CustomerSftpServiceImpl")
public class CustomerSftpServiceImpl extends AbstractFtpService implements IFtpService {
@Value("${customer.sftp.user}")
private String username;
@Value("${customer.sftp.password}")
private String password;
@Value("${customer.sftp.host}")
private String host;
@Value("${customer.sftp.directory}")
private String directory;
@Value("${customer.sftp.port}")
private int port;
/**
* @param request 请求参数对象
* @param retryTime 上传失败重试次数
* @return ture:上传成功,false:上传失败
* @throws Exception
*/
@Override
public Boolean send(Object request, int retryTime) throws Exception {
String fileName = "";
String path = "";
byte[] fileBytes = null;
if (request instanceof Map) {
fileName = (String) ((Map) request).get("fileName");
fileBytes = (byte[]) ((Map) request).get("fileBytes");
path = (String) ((Map) request).get("filePath");
}
if (StringUtils.isBlank(fileName)) {
throw new RuntimeException("文件名不能为空");
}
if (fileBytes == null) {
throw new RuntimeException("文件内容不能为空");
}
log.info("客服系统上传sftp, fileName:{}, path:{}", fileName, path);
FileInfo fileInfo = new FileInfo(fileName, fileBytes, path);
ServerInfo serverInfo = ServerInfo.builder()
.username(username)
.directory(directory)
.host(host)
.password(password)
.port(port)
.build();
send(fileInfo, serverInfo, 3);
return null;
}
@Override
public byte[] down(String fileName) throws IOException {
ServerInfo serverInfo = ServerInfo.builder()
.username(username).directory(directory)
.host(host).password(password)
.port(port)
.build();
byte[] result;
try {
fileName = directory.concat(fileName);
result = down(fileName, serverInfo, 1);
} catch (IOException ioEx) {
log.warn("客服系统下载文件,出现异常,fileName:{}, ex:{}", fileName, ExceptionUtils.getStackTrace(ioEx));
throw ioEx;
}
catch (Exception e) {
log.warn("客服系统下载文件,出现异常,fileName:{}, ex:{}", fileName, ExceptionUtils.getStackTrace(e));
throw new IOException("下载未知异常");
}
if (result == null) {
throw new IOException("文件为空");
}
return result;
}
}
package cn.quantgroup.customer.service.ftp;
import cn.quantgroup.customer.model.ftp.FileInfo;
import cn.quantgroup.customer.model.ftp.ServerInfo;
import org.apache.commons.lang3.NotImplementedException;
import java.io.IOException;
import java.util.List;
public interface IFtpService {
Object send(Object request);
/**
* @param request 请求参数对象
* @param retryTime 上传失败重试次数
* @return ture:上传成功,false:上传失败
* @throws Exception
*/
default Boolean send(Object request, int retryTime) throws Exception {
throw new NotImplementedException("send(Object request,int retryTime)方法没有实现!");
}
/**
* 文件下载
*
* @param fileName
* @return
* @throws IOException
*/
default byte[] down(String fileName) throws IOException {
throw new NotImplementedException("文件下载没有实现!");
}
/**
* SFTP 方式文件上传
*
* @param fileInfo  文件信息
* @param serverInfo  SFTP服务器信息
* @param retryTime 重试次数
* @return
* @throws Exception
*/
default boolean send(FileInfo fileInfo, ServerInfo serverInfo, int retryTime) throws Exception {
throw new NotImplementedException("send没有实现!");
}
/**
* 文件下载
*
* @param fullName 路径文件名称
* @param serverInfo 服务器信息
* @param retryTime 重试次数
* @return
* @throws Exception
*/
default byte[] down(String fullName, ServerInfo serverInfo, int retryTime) throws Exception {
throw new NotImplementedException("文件下载没有实现!");
}
/**
* 获取文件名列表
*
* @param serverInfo
* @return
* @throws Exception
*/
default List<String> listDirectory(ServerInfo serverInfo) throws Exception {
throw new NotImplementedException("查看目录下的所有文件没有实现!");
}
}
...@@ -17,6 +17,7 @@ import cn.quantgroup.customer.rest.vo.vcc.QuerySubmitRecordVo; ...@@ -17,6 +17,7 @@ import cn.quantgroup.customer.rest.vo.vcc.QuerySubmitRecordVo;
import cn.quantgroup.customer.service.IFastDFSService; import cn.quantgroup.customer.service.IFastDFSService;
import cn.quantgroup.customer.service.IOpSystemService; import cn.quantgroup.customer.service.IOpSystemService;
import cn.quantgroup.customer.service.IVccService; import cn.quantgroup.customer.service.IVccService;
import cn.quantgroup.customer.service.ftp.IFtpService;
import cn.quantgroup.customer.service.http.IHttpService; import cn.quantgroup.customer.service.http.IHttpService;
import cn.quantgroup.customer.util.IdUtil; import cn.quantgroup.customer.util.IdUtil;
import cn.quantgroup.user.retbean.XUser; import cn.quantgroup.user.retbean.XUser;
...@@ -35,12 +36,15 @@ import org.springframework.beans.factory.annotation.Autowired; ...@@ -35,12 +36,15 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.PageRequest;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.transaction.Transactional; import javax.transaction.Transactional;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*; import java.util.*;
import java.util.List; import java.util.List;
...@@ -60,6 +64,8 @@ public class VccServiceImpl implements IVccService { ...@@ -60,6 +64,8 @@ public class VccServiceImpl implements IVccService {
private IOpSystemService IOpSystemService; private IOpSystemService IOpSystemService;
@Autowired @Autowired
private IFastDFSService fastDfsService; private IFastDFSService fastDfsService;
@Autowired
private IFtpService ftpService;
@Autowired @Autowired
private UserSdkImpl userSdk; private UserSdkImpl userSdk;
...@@ -201,8 +207,10 @@ public class VccServiceImpl implements IVccService { ...@@ -201,8 +207,10 @@ public class VccServiceImpl implements IVccService {
List<String> list = Arrays.asList(split); List<String> list = Arrays.asList(split);
List<String> addressList = new ArrayList<>(); List<String> addressList = new ArrayList<>();
for (String baseUrl:list){ for (String baseUrl:list){
String viewUrl = fastDfsService.toUrl(baseUrl); // String viewUrl = fastDfsService.toUrl(baseUrl);
addressList.add(viewUrl); // addressList.add(viewUrl);
byte[] down = ftpService.down(baseUrl);
addressList.add(Base64.getEncoder().encodeToString(down));
} }
param.setCredentialsAddress(addressList); param.setCredentialsAddress(addressList);
return param; return param;
...@@ -270,14 +278,27 @@ public class VccServiceImpl implements IVccService { ...@@ -270,14 +278,27 @@ public class VccServiceImpl implements IVccService {
@Override @Override
public Map<String,String> fileUpload(MultipartFile file) throws Exception { public Map<String,String> fileUpload(MultipartFile file) throws Exception {
String name = file.getOriginalFilename(); // String name = file.getOriginalFilename();
log.info("fileUpload | filename={}",name); // log.info("fileUpload | filename={}",name);
String substring = name.substring(name.lastIndexOf(".") + 1); // String substring = name.substring(name.lastIndexOf(".") + 1);
String baseUrl = fastDfsService.uploadFile(file.getBytes(), substring); // String baseUrl = fastDfsService.uploadFile(file.getBytes(), substring);
String viewUrl = fastDfsService.toUrl(baseUrl); // String viewUrl = fastDfsService.toUrl(baseUrl);
// Map<String,String> map = new HashMap<>();
// map.put("baseUrl",baseUrl);
// map.put("viewUrl",viewUrl);
// return map;
String fileName = file.getOriginalFilename();
byte[] bytes = file.getBytes();
Map<String, Object> paramMap = new HashMap<>(8);
paramMap.put("fileName", fileName);
paramMap.put("fileBytes", bytes);
String filePath = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd")) + "/";
paramMap.put("filePath", filePath);
ftpService.send(paramMap, 3);
Map<String,String> map = new HashMap<>(); Map<String,String> map = new HashMap<>();
map.put("baseUrl",baseUrl); map.put("base64",Base64.getEncoder().encodeToString(bytes));
map.put("viewUrl",viewUrl); map.put("url",filePath + fileName);
return map; return map;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment