@@ -129,6 +129,38 @@ | |||||
<artifactId>spring-boot-starter-test</artifactId> | <artifactId>spring-boot-starter-test</artifactId> | ||||
<scope>test</scope> | <scope>test</scope> | ||||
</dependency> | </dependency> | ||||
<dependency> | |||||
<groupId>com.aliyun</groupId> | |||||
<artifactId>aliyun-java-sdk-core</artifactId> | |||||
<version>4.0.6</version> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>commons-net</groupId> | |||||
<artifactId>commons-net</artifactId> | |||||
<version>3.6</version> | |||||
<scope>compile</scope> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>com.jcraft</groupId> | |||||
<artifactId>jsch</artifactId> | |||||
<version>0.1.53</version> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>commons-fileupload</groupId> | |||||
<artifactId>commons-fileupload</artifactId> | |||||
<version>1.4</version> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>commons-io</groupId> | |||||
<artifactId>commons-io</artifactId> | |||||
<version>2.11.0</version> | |||||
</dependency> | |||||
<dependency> | |||||
<groupId>org.apache.httpcomponents</groupId> | |||||
<artifactId>httpclient</artifactId> | |||||
<version>4.5.7</version> | |||||
</dependency> | |||||
</dependencies> | </dependencies> | ||||
<build> | <build> | ||||
@@ -176,22 +208,22 @@ | |||||
<resources> | <resources> | ||||
<!-- 界面设计器 --> | <!-- 界面设计器 --> | ||||
<resource> | <resource> | ||||
<directory>E:/WORKSPACE/JJKJ-GIT/CODE/smtweb/sw-ui-design-vue/dist/</directory> | |||||
<directory>E:/jujia/source/sw-ui-design-vue/dist/</directory> | |||||
<targetPath>${basedir}/target/classes/static/design/ui</targetPath> | <targetPath>${basedir}/target/classes/static/design/ui</targetPath> | ||||
</resource> | </resource> | ||||
<!-- DB设计器 --> | <!-- DB设计器 --> | ||||
<resource> | <resource> | ||||
<directory>E:/WORKSPACE/JJKJ-GIT/CODE/smtweb/sw-db-design-vue/dist/</directory> | |||||
<directory>E:/jujia/source/sw-db-design-vue/dist/</directory> | |||||
<targetPath>${basedir}/target/classes/static/design/db</targetPath> | <targetPath>${basedir}/target/classes/static/design/db</targetPath> | ||||
</resource> | </resource> | ||||
<!-- 流程设计器 --> | <!-- 流程设计器 --> | ||||
<resource> | <resource> | ||||
<directory>E:/WORKSPACE/JJKJ-GIT/CODE/smtweb/sw-flow-design-vue/dist/</directory> | |||||
<directory>E:/jujia/source/sw-flow-design-vue/dist/</directory> | |||||
<targetPath>${basedir}/target/classes/static/design/flow</targetPath> | <targetPath>${basedir}/target/classes/static/design/flow</targetPath> | ||||
</resource> | </resource> | ||||
<!-- 预览脚手架 --> | <!-- 预览脚手架 --> | ||||
<resource> | <resource> | ||||
<directory>E:/WORKSPACE/JJKJ-GIT/CODE/smtweb/sw-framework-widget-vue/dist/</directory> | |||||
<directory>E:/jujia/source/sw-framework-widget-vue/dist/</directory> | |||||
<targetPath>${basedir}/target/classes/static/design/preview</targetPath> | <targetPath>${basedir}/target/classes/static/design/preview</targetPath> | ||||
</resource> | </resource> | ||||
<!-- 设定主资源目录,入口跳转页等 --> | <!-- 设定主资源目录,入口跳转页等 --> | ||||
@@ -0,0 +1,38 @@ | |||||
package cc.smtweb.system.bpm.spring.config; | |||||
import cc.smtweb.framework.core.util.JsonUtil; | |||||
import lombok.Data; | |||||
import org.springframework.boot.context.properties.ConfigurationProperties; | |||||
import org.springframework.stereotype.Component; | |||||
@Data | |||||
@Component | |||||
@ConfigurationProperties(prefix = "smtweb.file") | |||||
public class FileConfigProperties { | |||||
/** | |||||
* 系统底层附件保存路径和访问路径 | |||||
*/ | |||||
private String localPath; | |||||
private String url; | |||||
/** | |||||
* 自建的附件上传路径和访问路径,支持ftp | |||||
*/ | |||||
private String attachTempPath;//临时文件保存路径 | |||||
private String attachPath;//保存路径 | |||||
private String attachHttpPath;//文件访问地址 | |||||
private String attachType;//上传类型sftp/ftp/local | |||||
private String attachFtpIp;//ftp IP地址 | |||||
private int attachFtpPort;//ftp 端口 | |||||
private String attachFtpUser;//ftp 用户名 | |||||
private String attachFtpPwd;//ftp 密码 | |||||
@Override | |||||
public String toString() { | |||||
return JsonUtil.encodeString(this); | |||||
} | |||||
} |
@@ -0,0 +1,427 @@ | |||||
package cc.smtweb.system.bpm.spring.controller; | |||||
import cc.smtweb.framework.core.common.R; | |||||
import cc.smtweb.framework.core.db.DbEngine; | |||||
import cc.smtweb.framework.core.util.Consts; | |||||
import cc.smtweb.framework.core.util.DateUtil; | |||||
import cc.smtweb.framework.core.util.PubUtil; | |||||
import cc.smtweb.system.bpm.spring.config.FileConfigProperties; | |||||
import cc.smtweb.system.bpm.spring.file.attach.AttachHelper; | |||||
import cc.smtweb.system.bpm.spring.file.attach.AttachUtil; | |||||
import cc.smtweb.system.bpm.util.UtilDownloadFile; | |||||
import cc.smtweb.system.bpm.util.UtilFile; | |||||
import cc.smtweb.system.bpm.util.UtilLogger; | |||||
import cc.smtweb.system.bpm.util.UtilMath; | |||||
import cc.smtweb.system.bpm.web.sys.base.attach.AttachInfo; | |||||
import lombok.extern.slf4j.Slf4j; | |||||
import org.apache.commons.io.FileUtils; | |||||
import org.slf4j.Logger; | |||||
import org.slf4j.LoggerFactory; | |||||
import org.springframework.beans.factory.annotation.Autowired; | |||||
import org.springframework.util.FileCopyUtils; | |||||
import org.springframework.web.bind.annotation.*; | |||||
import org.springframework.web.multipart.MultipartFile; | |||||
import org.springframework.web.multipart.MultipartHttpServletRequest; | |||||
import org.springframework.web.multipart.commons.CommonsMultipartResolver; | |||||
import sun.misc.BASE64Decoder; | |||||
import javax.imageio.ImageIO; | |||||
import javax.servlet.http.HttpServletRequest; | |||||
import javax.servlet.http.HttpServletResponse; | |||||
import java.awt.*; | |||||
import java.awt.image.BufferedImage; | |||||
import java.io.BufferedOutputStream; | |||||
import java.io.File; | |||||
import java.io.FileOutputStream; | |||||
import java.io.IOException; | |||||
import java.util.HashMap; | |||||
import java.util.Iterator; | |||||
import java.util.Map; | |||||
/** | |||||
* Created by AKmm at 11-6-14 上午10:44 | |||||
* 附件管理 | |||||
*/ | |||||
@Slf4j | |||||
@RestController | |||||
@RequestMapping("/api/attach") | |||||
public class AttachController { | |||||
private static Logger logger = LoggerFactory.getLogger(AttachController.class); | |||||
@Autowired | |||||
private FileConfigProperties properties; | |||||
@Autowired | |||||
private AttachHelper attachHelper; | |||||
@Autowired | |||||
private AttachUtil attachUtil; | |||||
@Autowired | |||||
private DbEngine dbEngine; | |||||
private BASE64Decoder decoder = new BASE64Decoder(); | |||||
/** | |||||
* | |||||
* @param request | |||||
* @param type 类型,如idcard:身份证、headImg:头像 | |||||
* @param ownerId 拥有者ID | |||||
* @param path 存储目录路径名,如:idcard | |||||
* @param attachIsTemp 是否临时文件:true/false 字符串 | |||||
* @param attachName 附件名称,如:XXXXX.jpg | |||||
* @param savePath 保存路径,指定文件保存目录,可为空 | |||||
* @return | |||||
* @throws Exception | |||||
*/ | |||||
@PostMapping({"/upload"}) | |||||
public R upload(HttpServletRequest request, @RequestParam(value = "type", required = false) String type, | |||||
@RequestParam(value = "ownerId", required = false) Long ownerId, | |||||
@RequestParam(value = "path", required = false) String path, | |||||
@RequestParam(value = "attachIsTemp", required = false) String attachIsTemp, | |||||
@RequestParam(value = "attachName", required = false) String attachName, | |||||
@RequestParam(value = "savePath", required = false) String savePath) throws Exception { | |||||
CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(request.getSession().getServletContext()); | |||||
//判断是否多文件上传 | |||||
if (!multipartResolver.isMultipart(request)) { | |||||
return R.error("文件不存在"); | |||||
} | |||||
MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest) request; | |||||
Iterator<String> itr = multiRequest.getFileNames(); | |||||
MultipartFile file = null; | |||||
while (itr.hasNext()) { | |||||
file = multiRequest.getFile(itr.next()); | |||||
AttachInfo attach = new AttachInfo(); | |||||
attach.setId(dbEngine.nextId()); | |||||
attach.setType(type);//附件类别 | |||||
if(null !=ownerId) { | |||||
attach.setOwnerId(ownerId);//附件拥有者id | |||||
} | |||||
attach.setPath(path);//附件路径 | |||||
attach.setPartyId(-1l); | |||||
attach.setTime(PubUtil.getLastTime()); | |||||
attach.setUserId(-1l); | |||||
attach.setIsTemp("true".equals(attachIsTemp) ? 1 : 0);//暂时没有有效拥有者标记 方便定时任务清除垃圾附件 | |||||
// 上传文件名 | |||||
final int i = file.getOriginalFilename().lastIndexOf("."); | |||||
if (i >= 0) { | |||||
attach.setSuffix(file.getOriginalFilename().substring(i)); | |||||
} | |||||
if (PubUtil.isEmptyStr(attachName)) { | |||||
attachName = file.getOriginalFilename(); | |||||
} | |||||
else { | |||||
attachName = attachName + attach.getSuffix(); | |||||
} | |||||
attach.setName(attachName); | |||||
Map<String, Object> ret = new HashMap<>(); | |||||
try { | |||||
// 上传文件域对象 | |||||
File upload = new File(attachHelper.getAttachTmpPath() + attach.getId() + attach.getSuffix()); | |||||
attach.setSize((long) FileCopyUtils.copy(file.getInputStream(), new BufferedOutputStream(new FileOutputStream(upload)))); | |||||
if (PubUtil.isEmpty(savePath)) { | |||||
localSaveAttach(attach, upload); | |||||
} else {//复制到指定目录 | |||||
String filePath; | |||||
if ("-".equals(savePath)) filePath = upload.getAbsolutePath(); | |||||
else { | |||||
filePath = savePath + DateUtil.nowDateTimeString() + UtilFile.FSChar + attach.getName(); | |||||
UtilFile.copy(upload, filePath, true); | |||||
} | |||||
} | |||||
} catch (Exception e) { | |||||
logger.error("上传文件失败", e); | |||||
return R.error("上传文件失败"); | |||||
} | |||||
return R.success(attach.getId()); | |||||
} | |||||
// 上传文件类型 | |||||
//String uploadContentType = file.getContentType(); | |||||
return R.error("上传文件失败"); | |||||
} | |||||
/** | |||||
* | |||||
* @param request | |||||
* @param response | |||||
* @param base64File 文件base64编码 | |||||
* @param attachId 附件ID,可为空,如果有,则替换此附件ID对应数据 | |||||
* @param type 类型,如idcard:身份证、headImg:头像 | |||||
* @param ownerId 拥有者ID | |||||
* @param path 存储目录路径名,如:idcard | |||||
* @param attachIsTemp 是否临时文件:true/false 字符串 | |||||
* @param attachName 附件名称,如:XXXXX.jpg | |||||
* @param savePath 保存路径,指定文件保存目录,可为空 | |||||
* @param suffix 文件后缀,如.jpg | |||||
* @return | |||||
* @throws Exception | |||||
*/ | |||||
@RequestMapping(value = "/uploadBase64", method = RequestMethod.POST) | |||||
public R uploadBase64(HttpServletRequest request, HttpServletResponse response, | |||||
@RequestParam(value = "base64File", required = false) String base64File, | |||||
@RequestParam(value = "attachId", required = false) Long attachId, | |||||
@RequestParam(value = "type", required = false) String type, | |||||
@RequestParam(value = "ownerId", required = false) Long ownerId, | |||||
@RequestParam(value = "path", required = false) String path, | |||||
@RequestParam(value = "attachIsTemp", required = false) String attachIsTemp, | |||||
@RequestParam(value = "attachName", required = false) String attachName, | |||||
@RequestParam(value = "savePath", required = false) String savePath, | |||||
@RequestParam(value = "suffix", required = false) String suffix | |||||
) throws Exception { | |||||
// UtilLogger.error("上传文件接收base64", base64File); | |||||
if (null == base64File || "".equals(base64File)){ | |||||
return R.error("文件不能为空"); | |||||
} | |||||
String str[]=base64File.split(","); | |||||
if(str.length>1){ | |||||
base64File=str[1]; | |||||
} | |||||
// 上传文件类型 | |||||
//String uploadContentType = file.getContentType(); | |||||
AttachInfo attach = null; | |||||
boolean isNew = PubUtil.isEmpty(attachId+""); | |||||
if (isNew) { | |||||
attach = new AttachInfo(); | |||||
} | |||||
else { | |||||
attach = dbEngine.findDao(AttachInfo.class).queryEntity(attachId); | |||||
if (attach == null) { | |||||
attach = new AttachInfo(); | |||||
isNew = true; | |||||
} else isNew = attach.isNew(); | |||||
} | |||||
attach.setId(attachId); | |||||
if (PubUtil.isEmpty(attachId+"")) attach.setId(dbEngine.nextId()); | |||||
attach.setType(type);//附件类别 | |||||
if(null !=ownerId) { | |||||
attach.setOwnerId(ownerId);//附件拥有者id | |||||
} | |||||
attach.setPath(path);//附件路径 | |||||
attach.setPartyId(-1l); | |||||
attach.setTime(PubUtil.getLastTime()); | |||||
attach.setUserId(-1l); | |||||
attach.setIsTemp("true".equals(attachIsTemp) ? 1 : 0);//暂时没有有效拥有者标记 方便定时任务清除垃圾附件 | |||||
attach.setTime(DateUtil.nowDateTimeLong()); | |||||
attach.setIsTemp("true".equals(attachIsTemp) ? 1 : 0);//暂时没有有效拥有者标记 方便定时任务清除垃圾附件 | |||||
// 上传文件名 | |||||
attach.setSuffix(suffix); | |||||
attach.setName(attachName); | |||||
Map<String, Object> ret = new HashMap<>(); | |||||
try { | |||||
//将base64转图片存到临时目录 | |||||
// 上传文件域对象 | |||||
//保存文件 | |||||
byte[] byt = decoder.decodeBuffer(base64File); | |||||
for (int i = 0, len = byt.length; i < len; ++i) { | |||||
if (byt[i] < 0) { | |||||
byt[i] += 256; | |||||
} | |||||
} | |||||
//创建保存目录,格式 类型目录/年月/日 | |||||
File upload = new File(attachHelper.getAttachTmpPath() + attach.getId() + attach.getSuffix()); | |||||
FileUtils.writeByteArrayToFile(upload, byt); | |||||
attach.setSize(upload.length()); | |||||
if (PubUtil.isEmpty(savePath)) { | |||||
localSaveAttach(attach, upload); | |||||
} else {//复制到指定目录 | |||||
String filePath; | |||||
if (Consts.NULL_STRING.equals(savePath)) filePath = upload.getAbsolutePath(); | |||||
else { | |||||
filePath = savePath + DateUtil.nowDateTimeString() + UtilFile.FSChar + attach.getName(); | |||||
UtilFile.copy(upload, filePath, true); | |||||
} | |||||
} | |||||
} catch (Exception e) { | |||||
UtilLogger.error("上传文件失败", e); | |||||
return R.error("上传文件失败"); | |||||
} | |||||
return R.success(attach.getId()); | |||||
} | |||||
@PostMapping({"/copyupload"}) | |||||
public R copyupload(HttpServletRequest request) throws Exception { | |||||
String type=request.getParameter("type"); | |||||
String attachId=request.getParameter("attachId"); | |||||
if(PubUtil.isEmpty(attachId)){ | |||||
return R.success(""); | |||||
} | |||||
AttachInfo attach = dbEngine.queryEntity(AttachInfo.class, Long.valueOf(attachId)); | |||||
if(null ==attach){ | |||||
return R.success(""); | |||||
} | |||||
String remoteName =attach.getId()+attach.getName().substring(attach.getName().lastIndexOf(".")); | |||||
String remotePath = attach.getPath(); | |||||
String filePath =attachHelper.getAttachTmpPath()+"tempFiles/"; | |||||
UtilFile.makeDir(filePath); | |||||
Map<String, String> map = null; | |||||
try { | |||||
attachUtil.downloadAttach(remotePath, remoteName, filePath); | |||||
String filePaths=filePath+remoteName; | |||||
attach.setId(dbEngine.nextId()); | |||||
attach.setType(type);//附件类别 | |||||
attach.setOwnerId(-1l);//附件拥有者id | |||||
attach.setPartyId(-1l); | |||||
attach.setTime(PubUtil.getLastTime()); | |||||
attach.setUserId(-1l); | |||||
attach.setName(attach.getId()+attach.getSuffix()); | |||||
// 上传文件域对象 | |||||
File upload = new File(filePaths); | |||||
// attach.setSize((long) FileCopyUtils.copy(file.getInputStream(), new BufferedOutputStream(new FileOutputStream(upload)))); | |||||
localSaveAttach(attach, upload); | |||||
}catch (Exception e){ | |||||
logger.error("上传文件失败", e); | |||||
return R.error("上传文件失败"); | |||||
} | |||||
return R.success(attach.getId()); | |||||
} | |||||
//保存处理附件 | |||||
private void localSaveAttach(final AttachInfo attach, final File upload) throws Exception { | |||||
try { | |||||
//一般附件,上传到服务器,并记录附件 | |||||
//传到ftp服务器上 | |||||
attachUtil.saveAttach(attach, upload.getPath(), false); | |||||
//写入数据库 | |||||
dbEngine.insertEntity(attach); | |||||
// String sql="insert into "+AttachInfo.ENTITY_NAME+" (attach_id,attach_name,attach_suffix,attach_owner_id,attach_path,attach_type,attach_size,attach_is_temp,attach_party_id,attach_time,attach_user_id,attach_count,attach_ref_id)" | |||||
} finally { | |||||
UtilFile.delFile(upload.getAbsolutePath()); | |||||
} | |||||
} | |||||
//将附件上传到ftp服务器上 | |||||
@RequestMapping(value = "/download", method = {RequestMethod.GET, RequestMethod.POST}) | |||||
public R down(HttpServletRequest request, HttpServletResponse response, @RequestParam(value = "attachId", required = false) Long attachId) throws Exception { | |||||
AttachInfo attach = dbEngine.queryEntity(AttachInfo.class,attachId); | |||||
if (null == attach) { | |||||
return R.error("附件不存在"); | |||||
} | |||||
final String remoteFileName = attach.getName(); | |||||
final String fileName = attach.getName(); | |||||
final String remotePath = attach.getPath(); | |||||
logger.info("下载附件:filePath:" + remotePath + ",fileName:" + fileName); | |||||
try { | |||||
attachUtil.downloadAttach(remotePath, remoteFileName, fileName, response); | |||||
attach.setCount(attach.getCount() + 1); | |||||
dbEngine.updateEntity(attach,"attach_count"); | |||||
} catch (Exception e) { | |||||
logger.error("附件下载失败",e); | |||||
R.error("附件下载失败"); | |||||
} | |||||
return null; | |||||
} | |||||
//图片附件显示路径 | |||||
@RequestMapping(value = "/showImg", method = {RequestMethod.GET, RequestMethod.POST}) | |||||
public R showImg(HttpServletRequest request, HttpServletResponse response, @RequestParam(value = "attachId", required = false) Long attachId) throws Exception { | |||||
AttachInfo attach = dbEngine.queryEntity(AttachInfo.class,attachId); | |||||
if (null == attach) { | |||||
return R.error("附件不存在"); | |||||
} | |||||
final String remoteFileName = attach.getName(); | |||||
final String fileName = attach.getName(); | |||||
final String remotePath = attach.getPath(); | |||||
try { | |||||
attachUtil.downloadAttach(remotePath, remoteFileName, fileName, response); | |||||
} catch (Exception e) { | |||||
logger.error("附件下载失败",e); | |||||
R.error("附件下载失败"); | |||||
} | |||||
return null; | |||||
} | |||||
//图片附件显示路径 | |||||
@RequestMapping(value = "/showImgThumb", method = {RequestMethod.GET, RequestMethod.POST}) | |||||
public R showImgThumb(HttpServletRequest request, HttpServletResponse response, @RequestParam(value = "attachId", required = false) Long attachId, | |||||
@RequestParam(value = "width", required = false,defaultValue = "100") String width, | |||||
@RequestParam(value = "heigh", required = false,defaultValue = "100") String heigh) throws Exception { | |||||
AttachInfo attach = dbEngine.queryEntity(AttachInfo.class,attachId); | |||||
if (null == attach) { | |||||
return R.error("附件不存在"); | |||||
} | |||||
final String remoteFileName = attach.getName(); | |||||
final String tempPath = System.getProperty("java.io.tmpdir"); | |||||
final String remotePath = attach.getPath(); | |||||
try { | |||||
String lfo = tempPath + "/" + remoteFileName; | |||||
String lfd = tempPath + "/thumb_" + attach.getId() + attach.getSuffix(); | |||||
attachUtil.downloadAttach(remotePath, remoteFileName, tempPath); | |||||
int w=Integer.valueOf(width); | |||||
int h=Integer.valueOf(heigh); | |||||
if (w <= 0) w = 100; | |||||
if (h <= 0) h = 100; | |||||
getImgThumb(lfo, lfd, w, h); | |||||
if (UtilFile.isFileExist(lfd)) { | |||||
UtilDownloadFile.downfileEx(response, lfd, attach.getName()); | |||||
} else if (UtilFile.isFileExist(lfo)) { | |||||
UtilDownloadFile.downfileEx(response, lfo, attach.getName()); | |||||
} | |||||
} catch (Exception e) { | |||||
logger.error("附件下载失败",e); | |||||
R.error("附件下载失败"); | |||||
} | |||||
return null; | |||||
} | |||||
private static boolean getImgThumb(String orgFile, String dstFile, int width, int height) { | |||||
BufferedImage bufferedImage; | |||||
try { | |||||
//read image file | |||||
bufferedImage = ImageIO.read(new File(orgFile)); | |||||
// create a blank, RGB, same width and height, and a white background | |||||
int w = bufferedImage.getWidth(), h = bufferedImage.getHeight(); | |||||
double r = 1; | |||||
if (w > width) { | |||||
r = 1.0 * width / w; | |||||
} | |||||
if (h > height) { | |||||
r = Math.min(1.0 * height / h, r); | |||||
} | |||||
if (!UtilMath.isEqualsZero(r - 1)) { | |||||
w = (int) Math.round(w * r); | |||||
h = (int) Math.round(h * r); | |||||
} | |||||
BufferedImage newBufferedImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); | |||||
//TYPE_INT_RGB:创建一个RBG图像,24位深度,成功将32位图转化成24位 | |||||
newBufferedImage.createGraphics().drawImage(bufferedImage.getScaledInstance(w, h, Image.SCALE_SMOOTH), 0, 0, Color.WHITE, null); | |||||
// write to jpeg file | |||||
ImageIO.write(newBufferedImage, "jpg", new File(dstFile)); | |||||
return true; | |||||
} catch (IOException e) { | |||||
logger.error("转换jpg错误:" + orgFile); | |||||
return false; | |||||
} | |||||
} | |||||
//删除附件 | |||||
@PostMapping({"/delete"}) | |||||
public R del(HttpServletRequest request, @RequestParam(value = "attachId", required = false) Long attachId) throws Exception { | |||||
try { | |||||
AttachInfo attach = dbEngine.queryEntity(AttachInfo.class,attachId); | |||||
if (null == attach) { | |||||
return R.error("附件不存在"); | |||||
} | |||||
attachHelper.deleteOneAttach(attach); | |||||
return R.success("附件删除成功"); | |||||
} catch (Exception e) { | |||||
logger.error("删除附件失败", e); | |||||
return R.error("删除附件失败"); | |||||
} | |||||
} | |||||
//按拥有者删除附件 | |||||
@PostMapping({"/deleteByOwnerId"}) | |||||
public R delByOwnerId(HttpServletRequest request, @RequestParam(value = "ownerId", required = false) String ownerId) throws Exception { | |||||
try { | |||||
attachHelper.deleteAttachByOwnerId(ownerId); | |||||
return R.success("附件删除成功"); | |||||
} catch (Exception e) { | |||||
logger.error("删除附件失败", e); | |||||
return R.error("删除附件失败"); | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,71 @@ | |||||
package cc.smtweb.system.bpm.spring.dataCacheInit; | |||||
import cc.smtweb.framework.core.cache.redis.RedisManager; | |||||
import cc.smtweb.framework.core.db.DbEngine; | |||||
import cc.smtweb.system.bpm.web.sys.base.attachFolder.AttachFolder; | |||||
import cc.smtweb.system.bpm.web.sys.base.attachFolder.pojo.AttachFolderPojo; | |||||
import org.springframework.beans.factory.annotation.Autowired; | |||||
import org.springframework.stereotype.Component; | |||||
import java.util.List; | |||||
/** | |||||
* 实体【[附件目录表](TB_SYS_ATTACH_FOLDER)】的缓存Buffer类 | |||||
*/ | |||||
@Component | |||||
public final class AttachFolderEntityBuffer { | |||||
@Autowired | |||||
private RedisManager redisManager; | |||||
@Autowired | |||||
private DbEngine dbEngine; | |||||
public static final String cacheKey="attach_folder_"; | |||||
//根据附件路径和期间获取对象 | |||||
public AttachFolderPojo getByPath(String attachPath, String period) { | |||||
return redisManager.get(cacheKey+attachPath + "_" + period, AttachFolderPojo.class); | |||||
} | |||||
//根据附件路径和期间获取当前最大序号 | |||||
public int getMaxSeq(String attachPath, String period) { | |||||
AttachFolderPojo bean = getByPath(attachPath, period); | |||||
if (bean == null) return 0; | |||||
return bean.getFolderMaxSeq(); | |||||
} | |||||
//根据附件路径和期间获取当前文件数 | |||||
public int getFileCount(String attachPath, String period) { | |||||
AttachFolderPojo bean = getByPath(attachPath, period); | |||||
if (bean == null) return 0; | |||||
return bean.getFolderFileCount().intValue(); | |||||
} | |||||
//初始化数据 | |||||
public void initData(){ | |||||
//查询所有数据 | |||||
String sql="select folder_id,folder_path,folder_period,folder_max_seq,folder_file_count from "+ AttachFolder.ENTITY_NAME; | |||||
List<AttachFolder> returnList = dbEngine.query(sql,AttachFolder.class); | |||||
if(null !=returnList && returnList.size()>0){ | |||||
for(AttachFolder pojo:returnList){ | |||||
AttachFolderPojo p=new AttachFolderPojo(); | |||||
p.setFolderId(pojo.getId()); | |||||
p.setFolderAttachPath(pojo.getPath()); | |||||
p.setFolderFileCount(pojo.getFileCount()); | |||||
p.setFolderPeriod(pojo.getPeriod()); | |||||
p.setFolderMaxSeq(pojo.getMaxSeq()); | |||||
redisManager.set(cacheKey+pojo.getPath()+"_"+pojo.getPeriod(),p,0); | |||||
} | |||||
} | |||||
} | |||||
//写入一个数据 | |||||
public void putOneData(AttachFolderPojo pojo){ | |||||
//查询所有数据 | |||||
redisManager.set(cacheKey+pojo.getFolderAttachPath()+"_"+pojo.getFolderPeriod(),pojo,0); | |||||
} | |||||
} |
@@ -0,0 +1,102 @@ | |||||
package cc.smtweb.system.bpm.spring.file.attach; | |||||
import cc.smtweb.framework.core.util.PubUtil; | |||||
import cc.smtweb.system.bpm.spring.config.FileConfigProperties; | |||||
import cc.smtweb.system.bpm.util.UtilDownloadFile; | |||||
import cc.smtweb.system.bpm.util.UtilFile; | |||||
import cc.smtweb.system.bpm.web.sys.base.attach.AttachInfo; | |||||
import org.springframework.beans.factory.annotation.Autowired; | |||||
import org.springframework.stereotype.Component; | |||||
import javax.servlet.http.HttpServletResponse; | |||||
import java.io.File; | |||||
import java.nio.file.Path; | |||||
import java.nio.file.Paths; | |||||
import java.util.ArrayList; | |||||
import java.util.List; | |||||
@Component | |||||
public final class AttachFileWork implements IAttachWorkIntf { | |||||
@Autowired | |||||
private FileConfigProperties properties; | |||||
private String getPath(String remoteFolderPath) { | |||||
String path =properties.getAttachPath(); | |||||
if (PubUtil.isNotEmpty(remoteFolderPath) && !path.endsWith("/") && !remoteFolderPath.startsWith("/")) | |||||
path = path + "/" + remoteFolderPath; | |||||
else path = path + remoteFolderPath; | |||||
path = path.replaceAll("-",""); | |||||
UtilFile.makeDir(path); | |||||
if (!path.endsWith("/")) path = path + "/"; | |||||
return path; | |||||
} | |||||
private String getFileName(String remoteFolderPath, String fileName) { | |||||
return getPath(remoteFolderPath) + fileName; | |||||
} | |||||
public void saveAttach(String remoteAttachName, String remoteFolderPath, String localAttach, boolean isDelLocal) throws Exception { | |||||
String dstFile = getFileName(remoteFolderPath, remoteAttachName); | |||||
if (isDelLocal) UtilFile.renameTo(localAttach, dstFile); | |||||
else UtilFile.copy(localAttach,dstFile); | |||||
} | |||||
@Override | |||||
public void copyAttach(String srcFileName, String desFileName, String remoteFolderPath, boolean isDelSrc) throws Exception { | |||||
String srcFile = getFileName(remoteFolderPath, srcFileName); | |||||
String dstFile = getFileName(remoteFolderPath, desFileName); | |||||
if (isDelSrc) UtilFile.renameTo(srcFile, dstFile); | |||||
else UtilFile.copy(srcFile, dstFile); | |||||
} | |||||
public void deletePath(final String remotePath) throws Exception { | |||||
UtilFile.delFile(getPath(remotePath)); | |||||
} | |||||
public void deleteAttach(final String remotePath, final String remoteName) throws Exception { | |||||
UtilFile.delFile(getFileName(remotePath, remoteName)); | |||||
} | |||||
public void downloadAttach(final String remotePath, final String remoteName, final String fileName, final HttpServletResponse response) throws Exception { | |||||
UtilDownloadFile.downfileEx(response, getFileName(remotePath, remoteName), fileName); | |||||
} | |||||
public void downloadAttach(final String remotePath, final String remoteName, final String localPath) throws Exception { | |||||
UtilFile.copy(getFileName(remotePath, remoteName), localPath + "/" + remoteName); | |||||
} | |||||
@Override | |||||
public void downloadAttach(String remotePath, String remoteName, String localPath, String localName) throws Exception { | |||||
UtilFile.copy(getFileName(remotePath, remoteName), localPath + "/" + localName); | |||||
} | |||||
public void showAttachImg(final String remotePath, final String remoteName, final HttpServletResponse response) throws Exception { | |||||
UtilDownloadFile.sendImgFile(response, remoteName); | |||||
} | |||||
public List<String> getAttachListFromFtp(final List<AttachInfo> attachlist, final String ownerType, final String localRoot) throws Exception { | |||||
final List<String> files = new ArrayList<>(); | |||||
String localPath = localRoot + "/" + ownerType + "/"; | |||||
UtilFile.makeDir(localPath); | |||||
String fileName; | |||||
File file; | |||||
for (AttachInfo attach : attachlist) { | |||||
fileName = localPath + attach.getName(); | |||||
file = new File(fileName); | |||||
if (!file.exists()) | |||||
UtilFile.copy(getFileName(attach.getPath(), attach.getName()), fileName); | |||||
files.add(fileName); | |||||
} | |||||
return files; | |||||
} | |||||
public void makeRemoteDir(String path) throws Exception { | |||||
UtilFile.makeDir(getPath(path)); | |||||
} | |||||
@Override | |||||
public Path getAttachPath(String remotePath, String remoteName) { | |||||
String path = getFileName(remotePath, remoteName); | |||||
return Paths.get(path); | |||||
} | |||||
} |
@@ -0,0 +1,222 @@ | |||||
package cc.smtweb.system.bpm.spring.file.attach; | |||||
import cc.smtweb.framework.core.util.PubUtil; | |||||
import cc.smtweb.system.bpm.spring.config.FileConfigProperties; | |||||
import cc.smtweb.system.bpm.util.UtilDownloadFile; | |||||
import cc.smtweb.system.bpm.util.UtilFile; | |||||
import cc.smtweb.system.bpm.util.ftp.FtpTask; | |||||
import cc.smtweb.system.bpm.util.ftp.FtpTaskManager; | |||||
import cc.smtweb.system.bpm.util.ftp.IFtpServerConfig; | |||||
import cc.smtweb.system.bpm.util.ftp.IFtpUtil; | |||||
import cc.smtweb.system.bpm.web.sys.base.attach.AttachInfo; | |||||
import org.apache.commons.io.IOUtils; | |||||
import org.slf4j.Logger; | |||||
import org.slf4j.LoggerFactory; | |||||
import org.springframework.beans.factory.annotation.Autowired; | |||||
import org.springframework.stereotype.Component; | |||||
import javax.servlet.http.HttpServletResponse; | |||||
import java.io.File; | |||||
import java.io.InputStream; | |||||
import java.nio.file.Path; | |||||
import java.util.ArrayList; | |||||
import java.util.List; | |||||
/** | |||||
* Created by AKmm at 2011-2-23 16:35:49 | |||||
* ftp工作服务 | |||||
*/ | |||||
@Component | |||||
public final class AttachFtpWork implements IAttachWorkIntf { | |||||
Logger logger = LoggerFactory.getLogger(AttachFtpWork.class); | |||||
@Autowired | |||||
private FileConfigProperties properties; | |||||
private String getPath(String remoteFolderPath) { | |||||
String path = properties.getAttachPath(); | |||||
if (PubUtil.isNotEmpty(remoteFolderPath) && !path.endsWith("/") && !remoteFolderPath.startsWith("/")) | |||||
path = path + "/" + remoteFolderPath; | |||||
else path = path + remoteFolderPath; | |||||
path = path.replaceAll("-", ""); | |||||
UtilFile.makeDir(path); | |||||
if (!path.endsWith("/")) path = path + "/"; | |||||
logger.info("远程附件路径:" + path); | |||||
return path; | |||||
} | |||||
public FtpTaskManager getFtpManager() { | |||||
return FtpTaskManager.getInstance("ATTACH_FTP", new IFtpServerConfig() { | |||||
@Override | |||||
public boolean isSFTP() { | |||||
return "sftp".equalsIgnoreCase(properties.getAttachType()); | |||||
} | |||||
@Override | |||||
public String getServerIp() { | |||||
return properties.getAttachFtpIp(); | |||||
} | |||||
@Override | |||||
public Integer getPort() { | |||||
return properties.getAttachFtpPort(); | |||||
} | |||||
@Override | |||||
public String getUserName() { | |||||
return properties.getAttachFtpUser(); | |||||
} | |||||
@Override | |||||
public String getPassword() { | |||||
return properties.getAttachFtpPwd(); | |||||
} | |||||
}); | |||||
} | |||||
public void saveAttach(String remoteAttachName, String remoteFolderPath, String localAttach, boolean isDelLocal) throws Exception { | |||||
getFtpManager().uploadToFtp(remoteAttachName, getPath(remoteFolderPath), localAttach, isDelLocal); | |||||
} | |||||
@Override | |||||
public void copyAttach(String srcFileName, String desFileName, String remoteFolderPath, boolean isDelSrc) throws Exception { | |||||
getFtpManager().execute(new FtpTask() { | |||||
public Object execute(IFtpUtil ftp) throws Exception { | |||||
if (!ftp.existsFile(srcFileName, getPath(remoteFolderPath))) return null; | |||||
ftp.setRemoteDir("/"); | |||||
ftp.mkdir(remoteFolderPath); | |||||
ftp.rename(remoteFolderPath, srcFileName, desFileName); | |||||
return null; | |||||
} | |||||
}); | |||||
} | |||||
public void deletePath(final String remotePath) throws Exception { | |||||
getFtpManager().execute(new FtpTask() { | |||||
public Object execute(IFtpUtil ftp) throws Exception { | |||||
ftp.deleteFolder(remotePath); | |||||
return null; | |||||
} | |||||
}); | |||||
} | |||||
public void deleteAttach(final String remotePath, final String remoteName) throws Exception { | |||||
getFtpManager().execute(new FtpTask() { | |||||
public Object execute(IFtpUtil ftp) throws Exception { | |||||
ftp.deleteFile(getPath(remotePath), remoteName); | |||||
return null; | |||||
} | |||||
}); | |||||
} | |||||
public void downloadAttach(final String remotePath, final String remoteName, final String fileName, final HttpServletResponse response) throws Exception { | |||||
getFtpManager().execute(new FtpTask() { | |||||
public Object execute(IFtpUtil ftp) throws Exception { | |||||
InputStream in; | |||||
in = ftp.downloadFile(getPath(remotePath), remoteName); | |||||
if (in == null) return null; | |||||
try { | |||||
UtilDownloadFile.downfileStream(response, fileName, 0, in); | |||||
} finally { | |||||
IOUtils.closeQuietly(in); | |||||
ftp.completePendingCommand(); | |||||
} | |||||
return null; | |||||
} | |||||
}); | |||||
} | |||||
@Override | |||||
public void showAttachImg(final String remotePath, final String remoteName, final HttpServletResponse response) throws Exception { | |||||
getFtpManager().execute(new FtpTask() { | |||||
public Object execute(IFtpUtil ftp) throws Exception { | |||||
InputStream in = null; | |||||
try { | |||||
in = ftp.downloadFile(getPath(remotePath), remoteName); | |||||
} catch (Exception e) { | |||||
e.printStackTrace(); | |||||
} | |||||
if (in == null) return null; | |||||
try { | |||||
UtilDownloadFile.sendImgStream(response, in); | |||||
} finally { | |||||
IOUtils.closeQuietly(in); | |||||
ftp.completePendingCommand(); | |||||
} | |||||
return null; | |||||
} | |||||
}); | |||||
} | |||||
public void downloadAttach(final String remotePath, final String remoteName, final String localPath) throws Exception { | |||||
getFtpManager().execute(new FtpTask() { | |||||
public Object execute(IFtpUtil ftp) throws Exception { | |||||
try { | |||||
ftp.downloadFile(getPath(remotePath), remoteName, localPath); | |||||
} catch (Exception e) { | |||||
e.printStackTrace(); | |||||
} | |||||
return null; | |||||
} | |||||
}); | |||||
} | |||||
@Override | |||||
public void downloadAttach(String remotePath, String remoteName, String localPath, String localName) throws Exception { | |||||
getFtpManager().execute(new FtpTask() { | |||||
public Object execute(IFtpUtil ftp) throws Exception { | |||||
try { | |||||
ftp.downloadFileEx(getPath(remotePath), remoteName,localPath + File.separator + localName ); | |||||
} catch (Exception e) { | |||||
e.printStackTrace(); | |||||
} | |||||
return null; | |||||
} | |||||
}); | |||||
} | |||||
public List<String> getAttachListFromFtp(final List<AttachInfo> attachlist, final String ownerType, final String localRoot) throws Exception { | |||||
final List<String> files = new ArrayList<String>(); | |||||
getFtpManager().execute(new FtpTask() { | |||||
public Object execute(IFtpUtil ftp) throws Exception { | |||||
String localPath = localRoot + UtilFile.FSChar + ownerType + UtilFile.FSChar; | |||||
File file = new File(localPath); | |||||
if (!file.exists()) { | |||||
file.mkdirs(); | |||||
} | |||||
String fileName; | |||||
for (AttachInfo attach : attachlist) { | |||||
fileName = localPath + attach.getName(); | |||||
file = new File(fileName); | |||||
if (!file.exists()) | |||||
try { | |||||
ftp.downloadFileEx(getPath(attach.getPath()), attach.getName(), fileName); | |||||
} catch (Exception e) { | |||||
e.printStackTrace(); | |||||
} | |||||
files.add(fileName); | |||||
} | |||||
return null; | |||||
} | |||||
}); | |||||
return files; | |||||
} | |||||
public void makeRemoteDir(final String path) throws Exception { | |||||
getFtpManager().execute(new FtpTask() { | |||||
public Object execute(IFtpUtil ftp) throws Exception { | |||||
ftp.setRemoteDir(path); | |||||
return null; | |||||
} | |||||
}); | |||||
} | |||||
@Override | |||||
public Path getAttachPath(String remotePath, String remoteName) { | |||||
throw new UnsupportedOperationException("FTP的还没用到,没开发,暂不支持"); | |||||
} | |||||
} |
@@ -0,0 +1,283 @@ | |||||
package cc.smtweb.system.bpm.spring.file.attach; | |||||
import cc.smtweb.framework.core.db.DbEngine; | |||||
import cc.smtweb.framework.core.util.PubUtil; | |||||
import cc.smtweb.system.bpm.spring.config.FileConfigProperties; | |||||
import cc.smtweb.system.bpm.util.UtilFile; | |||||
import cc.smtweb.system.bpm.util.UtilMath; | |||||
import cc.smtweb.system.bpm.web.sys.base.attach.AttachInfo; | |||||
import org.slf4j.Logger; | |||||
import org.slf4j.LoggerFactory; | |||||
import org.springframework.beans.factory.annotation.Autowired; | |||||
import org.springframework.stereotype.Component; | |||||
import java.io.File; | |||||
import java.util.ArrayList; | |||||
import java.util.List; | |||||
import java.util.Map; | |||||
/** | |||||
* Created by AKmm at 11-6-15 下午3:32 | |||||
* 附件管理 | |||||
*/ | |||||
@Component | |||||
public final class AttachHelper { | |||||
Logger logger = LoggerFactory.getLogger(AttachHelper.class); | |||||
@Autowired | |||||
private FileConfigProperties properties; | |||||
@Autowired | |||||
private DbEngine dbEngine; | |||||
@Autowired | |||||
private AttachUtil attachUtil; | |||||
//得到附件临时目录 | |||||
public String getAttachTmpPath() { | |||||
String tmp_attach = properties.getAttachTempPath(); | |||||
if (!tmp_attach.endsWith("/")) tmp_attach += "/"; | |||||
File file = new File(tmp_attach); | |||||
if (!file.exists()) { | |||||
file.mkdirs(); | |||||
} | |||||
return tmp_attach; | |||||
} | |||||
//删除ftp服务器的文件 | |||||
public boolean deleteOneAttach(String attachId) throws Exception { | |||||
if (PubUtil.isEmpty(attachId)) return true; | |||||
AttachInfo attachInfo = dbEngine.queryEntity(AttachInfo.class, Long.valueOf(attachId)); | |||||
if(null == attachInfo){ | |||||
return true; | |||||
} | |||||
boolean deleteSuccess = deleteAttachInFtpServer(attachInfo.getPath(), attachInfo.getName()); | |||||
if (deleteSuccess) { | |||||
dbEngine.deleteEntity(attachInfo); | |||||
} | |||||
return deleteSuccess; | |||||
} | |||||
//删除ftp服务器的文件 | |||||
public boolean deleteOneAttach(AttachInfo bean) throws Exception { | |||||
boolean deleteSuccess = deleteAttachInFtpServer(bean.getPath(), bean.getName()); | |||||
if (deleteSuccess) { | |||||
dbEngine.deleteEntity(bean); | |||||
} | |||||
return deleteSuccess; | |||||
} | |||||
//删除ftp服务器的文件夹 | |||||
public void deleteFolder(final String remotePath) throws Exception { | |||||
attachUtil.deletePath(remotePath); | |||||
} | |||||
public List<AttachInfo> getAttachListByOwnerId(String ownerId) throws Exception { | |||||
return dbEngine.query("select * from "+AttachInfo.ENTITY_NAME+" where attach_owner_id=? ",AttachInfo.class,ownerId); | |||||
} | |||||
public List<AttachInfo> listAttachListByOwnerIdAndType(String ownerId, String attach_type) throws Exception { | |||||
return dbEngine.query("select * from "+AttachInfo.ENTITY_NAME+" where attach_owner_id=? and attach_type=? ",AttachInfo.class,ownerId,attach_type); | |||||
} | |||||
public int getAttachCountByOwnerId(String ownerId) throws Exception { | |||||
return dbEngine.queryInt("select count(0) from "+AttachInfo.ENTITY_NAME+" where attach_owner_id=? ",ownerId); | |||||
} | |||||
//根据附件拥有者和附件类型删除 | |||||
public boolean deleteAttachByOwnerIdAndType(String ownerId, String attachType) throws Exception { | |||||
final List<AttachInfo> list = listAttachListByOwnerIdAndType(ownerId, attachType); | |||||
return deleteAttachListEx(list); | |||||
} | |||||
public boolean deleteAttachByOwnerId(String ownerId) throws Exception { | |||||
final List<AttachInfo> list = getAttachListByOwnerId(ownerId); | |||||
return deleteAttachListEx(list); | |||||
} | |||||
//批量删除 | |||||
public boolean deleteAttachList(List<String> attachIdList) throws Exception { | |||||
if (PubUtil.isEmpty(attachIdList)) return false; | |||||
dbEngine.update("delete from "+AttachInfo.ENTITY_NAME+" where attach_id in(" + PubUtil.getSqlInIds(attachIdList) + ")"); | |||||
return true; | |||||
} | |||||
public boolean deleteAttachListEx(List<AttachInfo> list) throws Exception { | |||||
boolean result = true; | |||||
for (AttachInfo bean : list) { | |||||
if (!deleteAttachInFtpServer(bean.getPath(), bean.getName())) { | |||||
result = false; | |||||
break; | |||||
} | |||||
} | |||||
if (result) { | |||||
for (AttachInfo bean : list) { | |||||
dbEngine.deleteEntity(bean); | |||||
} | |||||
} | |||||
return result; | |||||
} | |||||
//删除在ftp服务器上的附件 | |||||
public boolean deleteAttachInFtpServer(String remotePath, String remoteName) { | |||||
try { | |||||
attachUtil.deleteAttach(remotePath, remoteName); | |||||
} catch (Exception e) { | |||||
e.printStackTrace(); | |||||
return false; | |||||
} | |||||
return true; | |||||
} | |||||
/** | |||||
* 下载附件 | |||||
* | |||||
* @param attachId 附件id | |||||
* @param localPath 要下载到的本地路径 | |||||
* @return 返回文件名 | |||||
* @throws Exception | |||||
*/ | |||||
public String getAttachFromFtp(final String attachId, final String localPath) throws Exception { | |||||
AttachInfo attach = dbEngine.queryEntity(AttachInfo.class, Long.valueOf(attachId)); | |||||
if (null == attach) throw new Exception("附件不存在!"); | |||||
final String remoteFileName = attach.getName(); | |||||
final String remotePath = attach.getPath(); | |||||
attachUtil.downloadAttach(remotePath, remoteFileName, localPath); | |||||
return remoteFileName; | |||||
} | |||||
/** | |||||
* 下载附件 | |||||
* | |||||
* @param attachId 附件id | |||||
* @param localPath 要下载到的本地路径 | |||||
* @return 返回文件名 | |||||
* @throws Exception | |||||
*/ | |||||
public String getAttachFromFtp(final String attachId, final String localPath, String localName) throws Exception { | |||||
AttachInfo attach = dbEngine.queryEntity(AttachInfo.class, Long.valueOf(attachId)); | |||||
if (null == attach) throw new Exception("附件不存在!"); | |||||
final String remoteFileName = attach.getName(); | |||||
final String remotePath = attach.getPath(); | |||||
attachUtil.downloadAttach(remotePath, remoteFileName, localPath, localName); | |||||
return remoteFileName; | |||||
} | |||||
/** | |||||
* 下载附件 | |||||
* | |||||
* @param attachlist 附件列表 | |||||
* @param ownerType 附件类别 | |||||
* @return 返回文件名列表,本地有此文件将不再下载 | |||||
* @throws Exception | |||||
*/ | |||||
private List<String> getAttachListFromFtp(final List<AttachInfo> attachlist, final String ownerType) throws Exception { | |||||
return attachUtil.getAttachListFromFtp(attachlist, ownerType, getAttachTmpPath()); | |||||
} | |||||
/** | |||||
* 下载附件 | |||||
* | |||||
* @param ownerId 附件拥有者id | |||||
* @param ownerType 附件类别 | |||||
* @return 返回文件名列表,本地有此文件将不再下载 | |||||
* @throws Exception | |||||
*/ | |||||
public List<String> getAttachsFromFtp(final String ownerId, final String ownerType) throws Exception { | |||||
final List<AttachInfo> attachlist = getAttachListByOwnerId(ownerId); | |||||
return getAttachListFromFtp(attachlist, ownerType); | |||||
} | |||||
/** | |||||
* 下载附件 | |||||
* | |||||
* @param attachIds 附件id | |||||
* @param ownerType 附件类别 | |||||
* @return 返回文件名列表,本地有此文件将不再下载 | |||||
* @throws Exception | |||||
*/ | |||||
public List<String> getAttachsFromFtp(final List<String> attachIds, final String ownerType) throws Exception { | |||||
List<Object> paras = new ArrayList<Object>(); | |||||
if (PubUtil.isNotEmpty(attachIds)) { | |||||
StringBuilder sb = new StringBuilder(128); | |||||
for(int i=0;i<attachIds.size();i++){ | |||||
if(i==0){ | |||||
sb.append(" attach_id=? "); | |||||
}else{ | |||||
sb.append(" or attach_id=? "); | |||||
} | |||||
paras.add(attachIds.get(i)); | |||||
} | |||||
final List<AttachInfo> attachlist =dbEngine.queryWhere(AttachInfo.class,sb.toString(),paras.toArray()); | |||||
if (null == attachlist || attachlist.size()<1) throw new Exception("附件不存在!"); | |||||
return getAttachListFromFtp(attachlist, ownerType); | |||||
} | |||||
return new ArrayList<>(); | |||||
} | |||||
/** | |||||
* 得到文件大小 | |||||
* | |||||
* @return | |||||
*/ | |||||
public String getSizeStr(long fileSize) { | |||||
if (fileSize < 1024) return fileSize + "B"; | |||||
double n = fileSize * 1.0 / 1024; | |||||
if (UtilMath.compare(n, 1024) < 0) return UtilMath.toStdNumberString(n, 0) + "KB"; | |||||
n = n / 1024; | |||||
return UtilMath.toStdNumberString(n) + "MB"; | |||||
} | |||||
/** | |||||
* 清除临时标志 | |||||
* | |||||
* @param attach_owner_id 拥有者 | |||||
* @throws Exception | |||||
*/ | |||||
public void removeTempTag(String attach_owner_id) throws Exception { | |||||
dbEngine.update("update "+AttachInfo.ENTITY_NAME+" set attach_is_temp=0 WHERE attach_owner_id=? AND attach_is_temp=1 ",attach_owner_id); | |||||
} | |||||
public String copyupload(String type,Long attachId) { | |||||
AttachInfo attach = dbEngine.queryEntity(AttachInfo.class, attachId); | |||||
if(attach==null){ | |||||
return ""; | |||||
} | |||||
String remoteName =attach.getId()+attach.getName().substring(attach.getName().lastIndexOf(".")); | |||||
String remotePath = attach.getPath(); | |||||
String filePath =getAttachTmpPath()+"tempFiles/"; | |||||
UtilFile.makeDir(filePath); | |||||
Map<String, String> map = null; | |||||
try { | |||||
attachUtil.downloadAttach(remotePath, remoteName, filePath); | |||||
String filePaths=filePath+remoteName; | |||||
attach.setId(dbEngine.nextId()); | |||||
attach.setType(type);//附件类别 | |||||
attach.setOwnerId(-1l);//附件拥有者id | |||||
attach.setPartyId(-1l); | |||||
attach.setTime(PubUtil.getLastTime()); | |||||
attach.setUserId(-1l); | |||||
attach.setName(attach.getId()+attach.getSuffix()); | |||||
// 上传文件域对象 | |||||
File upload = new File(filePaths); | |||||
// attach.setAttachSize((long) FileCopyUtils.copy(file.getInputStream(), new BufferedOutputStream(new FileOutputStream(upload)))); | |||||
try { | |||||
//一般附件,上传到服务器,并记录附件 | |||||
//传到ftp服务器上 | |||||
attachUtil.saveAttach(attach, upload.getPath(), false); | |||||
//写入数据库 | |||||
dbEngine.insertEntity(attach); | |||||
} finally { | |||||
UtilFile.delFile(upload.getAbsolutePath()); | |||||
} | |||||
}catch (Exception e){ | |||||
logger.error("复制文件失败", e); | |||||
return ""; | |||||
} | |||||
return attach.getId()+""; | |||||
} | |||||
} |
@@ -0,0 +1,135 @@ | |||||
package cc.smtweb.system.bpm.spring.file.attach; | |||||
import cc.smtweb.framework.core.db.DbEngine; | |||||
import cc.smtweb.framework.core.util.DateUtil; | |||||
import cc.smtweb.framework.core.util.PubUtil; | |||||
import cc.smtweb.system.bpm.spring.config.FileConfigProperties; | |||||
import cc.smtweb.system.bpm.spring.dataCacheInit.AttachFolderEntityBuffer; | |||||
import cc.smtweb.system.bpm.web.sys.base.attach.AttachInfo; | |||||
import cc.smtweb.system.bpm.web.sys.base.attachFolder.AttachFolder; | |||||
import cc.smtweb.system.bpm.web.sys.base.attachFolder.pojo.AttachFolderPojo; | |||||
import org.springframework.beans.factory.annotation.Autowired; | |||||
import org.springframework.stereotype.Component; | |||||
import javax.servlet.http.HttpServletResponse; | |||||
import java.nio.file.Path; | |||||
import java.util.List; | |||||
/** | |||||
* Created by AKmm at 2011-2-23 15:06:56 | |||||
* 附件存储工具,按存储方式决定保存在 | |||||
*/ | |||||
@Component | |||||
public final class AttachUtil { | |||||
//一个文件夹下最多允许多少文件 | |||||
private final static int MAX_FILE_COUNT = 1000; | |||||
private static IAttachWorkIntf worker; | |||||
@Autowired | |||||
private FileConfigProperties properties; | |||||
@Autowired | |||||
private AttachFolderEntityBuffer attachFolderEntityBuffer; | |||||
@Autowired | |||||
private DbEngine dbEngine; | |||||
@Autowired | |||||
private AttachFtpWork attachFtpWork; | |||||
@Autowired | |||||
private AttachFileWork attachFileWork; | |||||
static { | |||||
// init(); | |||||
} | |||||
public void init() { | |||||
final String at = PubUtil.checkNull(properties.getAttachType()).toLowerCase(); | |||||
if ("ftp".equals(at) || "sftp".equals(at)) | |||||
worker = attachFtpWork; | |||||
else worker = attachFileWork; | |||||
} | |||||
private void checkAttachFolder(final AttachInfo attach) throws Exception { | |||||
final String period = DateUtil.getNowYm(); | |||||
AttachFolderPojo folder = attachFolderEntityBuffer.getByPath(attach.getPath(), period); | |||||
AttachFolder entity=new AttachFolder(); | |||||
boolean isNew = false; | |||||
if (folder == null) { | |||||
isNew = true; | |||||
folder = new AttachFolderPojo(); | |||||
folder.setFolderId(dbEngine.nextId()); | |||||
folder.setFolderAttachPath(attach.getPath()); | |||||
folder.setFolderPeriod(period); | |||||
folder.setFolderMaxSeq(1); | |||||
entity.setPath(attach.getPath()); | |||||
entity.setPeriod(period); | |||||
entity.setMaxSeq(1); | |||||
} | |||||
if (folder.getFolderFileCount() >= MAX_FILE_COUNT) { | |||||
folder.setFolderMaxSeq(folder.getFolderMaxSeq() + 1); | |||||
folder.setFolderFileCount(0l); | |||||
entity.setMaxSeq(folder.getFolderMaxSeq() + 1); | |||||
entity.setFileCount(0); | |||||
} | |||||
folder.setFolderFileCount(folder.getFolderFileCount() + 1); | |||||
entity.setFileCount(folder.getFolderFileCount() + 1); | |||||
entity.setId(folder.getFolderId()); | |||||
//检查并确定远程目录 | |||||
if (isNew) { | |||||
// dbEngine.update("insert into "+AttachFolderEntity.ENTITY_NAME+" (folder_id,attach_path,folder_period,max_seq,file_count)values(?,?,?,?,?)",entity.getFolderId(),entity.getAttachPath(),entity.getFolderPeriod(),entity.getMaxSeq(),entity.getFileCount()); | |||||
dbEngine.insertEntity(entity, "folder_id,folder_path,folder_period,folder_max_seq,folder_file_count"); | |||||
} else { | |||||
// dbEngine.update("update "+AttachFolderEntity.ENTITY_NAME+" set max_seq=?,file_count=? where folder_id=?",new Object[]{entity.getMaxSeq(),entity.getFileCount(),entity.getFolderId()}); | |||||
dbEngine.updateEntity(entity, "folder_max_seq,folder_file_count"); | |||||
} | |||||
attach.setPath(attach.getPath() + "/" + period + "/" + folder.getFolderMaxSeq()); | |||||
attachFolderEntityBuffer.putOneData(folder); | |||||
} | |||||
public void saveAttach(final AttachInfo attach, String localAttach, boolean isDelLocal) throws Exception { | |||||
synchronized (attach.getPath()) { | |||||
checkAttachFolder(attach); | |||||
saveAttach(attach.getName(), attach.getPath(), localAttach, false); | |||||
} | |||||
} | |||||
public void saveAttach(String remoteAttachName, String remoteFolderPath, String localAttach, boolean isDelLocal) throws Exception { | |||||
worker.saveAttach(remoteAttachName, remoteFolderPath, localAttach, isDelLocal); | |||||
} | |||||
public void copyAttach(String srcFileName, String desFileName, String remoteFolderPath, boolean isDelSrc) throws Exception { | |||||
worker.copyAttach(srcFileName, desFileName, remoteFolderPath, isDelSrc); | |||||
} | |||||
public void deletePath(String remotePath) throws Exception { | |||||
worker.deletePath(remotePath); | |||||
} | |||||
public void deleteAttach(String remotePath, String remoteName) throws Exception { | |||||
worker.deleteAttach(remotePath, remoteName); | |||||
} | |||||
public void downloadAttach(String remotePath, String remoteName, String fileName, HttpServletResponse response) throws Exception { | |||||
worker.downloadAttach(remotePath, remoteName, fileName, response); | |||||
} | |||||
public void downloadAttach(String remotePath, String remoteName, String localPath) throws Exception { | |||||
worker.downloadAttach(remotePath, remoteName, localPath); | |||||
} | |||||
public void downloadAttach(String remotePath, String remoteName, String localPath, String localName) throws Exception { | |||||
worker.downloadAttach(remotePath, remoteName, localPath, localName); | |||||
} | |||||
public List<String> getAttachListFromFtp(final List<AttachInfo> attachlist, final String ownerType, final String localRoot) throws Exception { | |||||
return worker.getAttachListFromFtp(attachlist, ownerType, localRoot); | |||||
} | |||||
public void makeRemoteDir(String path) throws Exception { | |||||
worker.makeRemoteDir(path); | |||||
} | |||||
public Path getAttachPath(String remotePath, String remoteName) throws Exception { | |||||
return worker.getAttachPath(remotePath, remoteName); | |||||
} | |||||
} |
@@ -0,0 +1,28 @@ | |||||
package cc.smtweb.system.bpm.spring.file.attach; | |||||
import cc.smtweb.system.bpm.web.sys.base.attach.AttachInfo; | |||||
/** | |||||
* Created by Akmm at 13-5-4 下午3:02 | |||||
* 附件处理跟踪 | |||||
*/ | |||||
public interface IAttachTraceIntf { | |||||
/** | |||||
* 附件上传后 | |||||
* | |||||
* @param filePath | |||||
* @param attach | |||||
* @throws Exception | |||||
*/ | |||||
void afterUpload(String filePath, AttachInfo attach) throws Exception; | |||||
/** | |||||
* 附件删除后 | |||||
* | |||||
* @param attach | |||||
* @throws Exception | |||||
*/ | |||||
void afterDel(AttachInfo attach) throws Exception; | |||||
} |
@@ -0,0 +1,115 @@ | |||||
package cc.smtweb.system.bpm.spring.file.attach; | |||||
import cc.smtweb.system.bpm.web.sys.base.attach.AttachInfo; | |||||
import javax.servlet.http.HttpServletResponse; | |||||
import java.nio.file.Path; | |||||
import java.util.List; | |||||
/** | |||||
* Created by AKmm at 2011-2-23 16:22:20 | |||||
* 附件存储操作接口 | |||||
*/ | |||||
public interface IAttachWorkIntf { | |||||
/** | |||||
* 保存附件 | |||||
* | |||||
* @param remoteAttachName 远程附件名 | |||||
* @param remoteFolderPath 远程路径 | |||||
* @param localAttach 本地文件名 | |||||
* @param isDelLocal 保存后是否删除本地 | |||||
* @throws Exception | |||||
*/ | |||||
void saveAttach(String remoteAttachName, String remoteFolderPath, String localAttach, boolean isDelLocal) throws Exception; | |||||
/** | |||||
* 复制附件 | |||||
* | |||||
* @param srcFileName 源文件 | |||||
* @param desFileName 新文件 | |||||
* @param remoteFolderPath 文件路径 | |||||
* @param isDelSrc 保存后是否删除源文件 | |||||
* @throws Exception | |||||
*/ | |||||
void copyAttach(String srcFileName, String desFileName, String remoteFolderPath, boolean isDelSrc) throws Exception; | |||||
/** | |||||
* 删除路径 | |||||
* | |||||
* @param remotePath 远程路径 | |||||
* @throws Exception | |||||
*/ | |||||
void deletePath(String remotePath) throws Exception; | |||||
/** | |||||
* 删除附件 | |||||
* | |||||
* @param remotePath 远程路径 | |||||
* @param remoteName 远程文件名 | |||||
* @return | |||||
*/ | |||||
void deleteAttach(String remotePath, String remoteName) throws Exception; | |||||
/** | |||||
* 下载附件到文件流 | |||||
* | |||||
* @param remotePath | |||||
* @param remoteName | |||||
* @param response | |||||
* @throws Exception | |||||
*/ | |||||
void downloadAttach(String remotePath, String remoteName, String fileName, HttpServletResponse response) throws Exception; | |||||
/** | |||||
* 下载到本地 | |||||
* | |||||
* @param remotePath 远端路径 | |||||
* @param remoteName 远端文件 | |||||
* @param localPath 本地路径 | |||||
* @throws Exception | |||||
*/ | |||||
void downloadAttach(String remotePath, String remoteName, String localPath) throws Exception; | |||||
/** | |||||
* 下载到本地 | |||||
* | |||||
* @param remotePath 远端路径 | |||||
* @param remoteName 远端文件 | |||||
* @param localPath 本地路径 | |||||
* @throws Exception | |||||
*/ | |||||
void downloadAttach(String remotePath, String remoteName, String localPath, String localName) throws Exception; | |||||
/** | |||||
* img显示 | |||||
* | |||||
* @param remotePath 远端路径 | |||||
* @param remoteName 远端文件 | |||||
* @param response | |||||
* @throws Exception | |||||
*/ | |||||
void showAttachImg(final String remotePath, final String remoteName, final HttpServletResponse response) throws Exception; | |||||
/** | |||||
* 批量下载文件到本地 | |||||
* | |||||
* @param attachlist | |||||
* @param ownerType | |||||
* @param localRoot | |||||
* @return | |||||
* @throws Exception | |||||
*/ | |||||
List<String> getAttachListFromFtp(List<AttachInfo> attachlist, String ownerType, String localRoot) throws Exception; | |||||
void makeRemoteDir(String path) throws Exception; | |||||
/** | |||||
* 获取文件路径 | |||||
* | |||||
*/ | |||||
Path getAttachPath(String remotePath, String remoteName); | |||||
} |
@@ -0,0 +1,27 @@ | |||||
package cc.smtweb.system.bpm.spring.initPlugin; | |||||
import cc.smtweb.system.bpm.spring.dataCacheInit.AttachFolderEntityBuffer; | |||||
import cc.smtweb.system.bpm.spring.file.attach.AttachUtil; | |||||
import org.springframework.beans.factory.annotation.Autowired; | |||||
import org.springframework.boot.ApplicationArguments; | |||||
import org.springframework.boot.ApplicationRunner; | |||||
import org.springframework.stereotype.Component; | |||||
/** | |||||
* @Author: zhangyulong | |||||
* @Date: 2021/9/17 15:31 | |||||
*/ | |||||
@Component | |||||
public class RunDataInit implements ApplicationRunner { | |||||
@Autowired | |||||
private AttachFolderEntityBuffer attachFolderEntityBuffer; | |||||
@Autowired | |||||
private AttachUtil attachUtil; | |||||
@Override | |||||
public void run(ApplicationArguments args) throws Exception { | |||||
attachFolderEntityBuffer.initData();//附件目录缓存 | |||||
attachUtil.init();//附件上传方式初始化 | |||||
} | |||||
} |
@@ -0,0 +1,135 @@ | |||||
package cc.smtweb.system.bpm.util; | |||||
import org.apache.commons.io.IOUtils; | |||||
import javax.servlet.http.HttpServletResponse; | |||||
import java.io.*; | |||||
public abstract class UtilDownloadFile { | |||||
public static void writePdf(HttpServletResponse response, InputStream inputStream) throws IOException { | |||||
InputStream bufIn = new BufferedInputStream(inputStream, 8192); | |||||
try { | |||||
OutputStream output = response.getOutputStream(); | |||||
response.setContentType("application/pdf"); | |||||
byte[] bs = new byte[8192]; | |||||
while (true) { | |||||
int nLen = bufIn.read(bs); | |||||
if (nLen <= 0) break; | |||||
output.write(bs, 0, nLen); | |||||
} | |||||
output.flush(); | |||||
} finally { | |||||
IOUtils.closeQuietly(bufIn); | |||||
} | |||||
} | |||||
/** | |||||
* Akmm 2008.8.29 增加,原方法在大文件时,必须先读完整个文件才开始下载, | |||||
* 新加方法边读边写response.getOutputStream,让客户端及时看到进度条 | |||||
* | |||||
* @param response r | |||||
* @param fileSrc 源文件名 | |||||
* @param fileOrigName 显示在reponse中的文件名称. | |||||
*/ | |||||
public static void downfileEx(HttpServletResponse response, String fileSrc, String fileOrigName) { | |||||
InputStream in = null; | |||||
try { | |||||
in = new BufferedInputStream(new FileInputStream(fileSrc), 8192); | |||||
downfileStream(response, fileOrigName, in.available(), in); | |||||
} catch (Exception e) { | |||||
// ignore | |||||
} finally { | |||||
IOUtils.closeQuietly(in); | |||||
} | |||||
} | |||||
/** | |||||
* Akmm 2008.8.29 增加,原方法在大文件时,必须先读完整个文件才开始下载, | |||||
* 新加方法边读边写response.getOutputStream,让客户端及时看到进度条 | |||||
*/ | |||||
public static void downfileStream(HttpServletResponse response, String fileName, int totalSize, InputStream in) { | |||||
OutputStream out = null; | |||||
try { | |||||
writeResponseHeader(response, fileName, totalSize); | |||||
out = response.getOutputStream(); | |||||
byte[] bs = new byte[8192]; | |||||
while (true) { | |||||
int nLen = in.read(bs); | |||||
if (nLen <= 0) break; | |||||
out.write(bs, 0, nLen); | |||||
} | |||||
out.flush(); | |||||
} catch (IOException e) { | |||||
UtilLogger.error("客户端下载过程取消或中断!", e); | |||||
} finally { | |||||
IOUtils.closeQuietly(out); | |||||
} | |||||
} | |||||
public static void sendImgFile(HttpServletResponse response, String fileSrc) { | |||||
InputStream in = null; | |||||
try { | |||||
in = new BufferedInputStream(new FileInputStream(fileSrc), 8192); | |||||
sendImgStream(response, in); | |||||
} catch (Exception e) { | |||||
// ignore | |||||
} finally { | |||||
IOUtils.closeQuietly(in); | |||||
} | |||||
} | |||||
/** | |||||
* Akmm 图片显示, | |||||
*/ | |||||
public static void sendImgStream(HttpServletResponse response, InputStream in) { | |||||
OutputStream out = null; | |||||
try { | |||||
out = response.getOutputStream(); | |||||
byte[] bs = new byte[8192]; | |||||
while (true) { | |||||
int nLen = in.read(bs); | |||||
if (nLen <= 0) break; | |||||
out.write(bs, 0, nLen); | |||||
} | |||||
out.flush(); | |||||
} catch (IOException e) { | |||||
UtilLogger.error("图片显示", e); | |||||
} finally { | |||||
IOUtils.closeQuietly(out); | |||||
} | |||||
} | |||||
public static void writeResponseHeader(HttpServletResponse response, String fileName, int totalSize) { | |||||
try { | |||||
/*解决中文文件名乱码的问题*/ | |||||
fileName = java.net.URLEncoder.encode(fileName, "UTF-8"); | |||||
} catch (Exception ex) { | |||||
// ignore | |||||
} | |||||
/* | |||||
例1.内嵌显示一个文件 | |||||
Content-disposition: inline; filename=foobar.pdf | |||||
例2.往response里附加一个文件 | |||||
Content-disposition: attachment; filename=foobar.pdf | |||||
*/ | |||||
//返回文件下载 | |||||
response.setContentType("APPLICATION/OCTET-STREAM"); | |||||
response.setCharacterEncoding("UTF-8"); | |||||
response.setHeader("GATM-Attch-Name", fileName); | |||||
response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\""); | |||||
if (totalSize > 0) response.setContentLength(totalSize); | |||||
} | |||||
/** | |||||
* 写空长度的内容到输出流. | |||||
*/ | |||||
public static void writeZeroLengthResponse(HttpServletResponse response, String fileName) { | |||||
try { | |||||
writeResponseHeader(response, fileName, 0); | |||||
response.flushBuffer(); | |||||
} catch (IOException e) { | |||||
// ignore e; | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,66 @@ | |||||
package cc.smtweb.system.bpm.util; | |||||
import cc.smtweb.framework.core.util.PubUtil; | |||||
import org.slf4j.Logger; | |||||
import org.slf4j.LoggerFactory; | |||||
import java.text.MessageFormat; | |||||
@SuppressWarnings("UnusedDeclaration") | |||||
public class UtilLogger { | |||||
private static final Logger logger = LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME); | |||||
private static String getOrigMsg(String message, Throwable e) { | |||||
if (message != null) return message; | |||||
return PubUtil.getOrigMsg(e); | |||||
} | |||||
public static void debug(String message) { | |||||
logger.debug(message); | |||||
} | |||||
public static void debug(String message, String module) { | |||||
logger.debug(MessageFormat.format("[{0}]{1}", module, message)); | |||||
} | |||||
public static void debug(String message, Throwable e) { | |||||
logger.debug(getOrigMsg(message, e), e); | |||||
} | |||||
public static void info(String message) { | |||||
logger.info(message); | |||||
} | |||||
public static void info(String message, String module) { | |||||
logger.info(MessageFormat.format("[{0}]{1}", module, message)); | |||||
} | |||||
public static void info(String message, Throwable e) { | |||||
logger.info(getOrigMsg(message, e), e); | |||||
} | |||||
public static void warn(String message) { | |||||
logger.warn(message); | |||||
} | |||||
public static void warn(String message, String module) { | |||||
logger.warn(MessageFormat.format("[{0}]{1}", module, message)); | |||||
} | |||||
public static void warn(String message, Throwable e) { | |||||
logger.warn(getOrigMsg(message, e), e); | |||||
} | |||||
public static void error(String message) { | |||||
logger.error(message); | |||||
} | |||||
public static void error(String message, String module) { | |||||
logger.error(MessageFormat.format("[{0}]{1}", module, message)); | |||||
} | |||||
public static void error(String message, Throwable e) { | |||||
if (e instanceof Exception) logger.info(message + PubUtil.getOrigMsg(e)); | |||||
else logger.error(getOrigMsg(message, e), e); | |||||
} | |||||
} |
@@ -0,0 +1,465 @@ | |||||
package cc.smtweb.system.bpm.util; | |||||
import cc.smtweb.framework.core.util.PubUtil; | |||||
import java.math.BigDecimal; | |||||
import java.math.RoundingMode; | |||||
import java.text.DecimalFormat; | |||||
/** | |||||
* Created with IntelliJ IDEA. | |||||
* User: AKhh | |||||
* Date: 12-12-25 下午1:02 | |||||
* To change this template use File | Settings | File Templates. | |||||
*/ | |||||
public class UtilMath { | |||||
//整数 | |||||
private static DecimalFormat dfLng = new DecimalFormat("##############0"); | |||||
private static DecimalFormat dfLong = new DecimalFormat("###,###,###,###,##0"); | |||||
//一位小数 | |||||
private static DecimalFormat df1 = new DecimalFormat("##############0.0"); | |||||
private static DecimalFormat df1Format = new DecimalFormat("###,###,###,###,##0.0"); | |||||
//两位小数 | |||||
private static DecimalFormat df2 = new DecimalFormat("##############0.00"); | |||||
private static DecimalFormat df2Format = new DecimalFormat("###,###,###,###,##0.00"); | |||||
//四位小数 | |||||
private static DecimalFormat df4 = new DecimalFormat("###,###,###,###,##0.0000"); | |||||
//六位小数 | |||||
private static DecimalFormat df6Number = new DecimalFormat("#######################0.000000"); | |||||
private static DecimalFormat df6NumberF = new DecimalFormat("#,###,###,###,###,###,##0.000000"); | |||||
public final static DecimalFormat stdAmountFormat = new DecimalFormat("###,###,###,###,##0.00"); | |||||
public final static DecimalFormat stdNumberFormat = new DecimalFormat("#0.00"); | |||||
public final static String DEF_NUM_TEN_THOUSAND = "10000";//万 | |||||
public static final double MAX_VALUE = 9999999999999.99D; | |||||
public static final double MIN_VALUE = -9999999999999.99D; | |||||
private final static BigDecimal ONE_BIG = new BigDecimal(1.00D); | |||||
private static final String UNIT = "万仟佰拾亿仟佰拾万仟佰拾元角分"; | |||||
private static final String DIGIT = "零壹贰叁肆伍陆柒捌玖"; | |||||
/** | |||||
* 4舍5入double,2位小数 | |||||
*/ | |||||
public static double roundDouble(double src) { | |||||
return roundDouble(src, 2); | |||||
} | |||||
/** | |||||
* 4舍5入double,N 位小数 | |||||
* @param src | |||||
* @param scale 小数位数 | |||||
* @return | |||||
*/ | |||||
public static double roundDouble(Object src, int scale) { | |||||
if (src == null) return 0.0; | |||||
String v = src.toString(); | |||||
if (PubUtil.isEmpty(v)) return 0.0; | |||||
if (scale < 0) scale = 2; | |||||
BigDecimal src_b = new BigDecimal(v); | |||||
BigDecimal src_v = src_b.divide(ONE_BIG, scale + 2, BigDecimal.ROUND_HALF_UP);// 4舍5入 | |||||
src_v = src_v.divide(ONE_BIG, scale, BigDecimal.ROUND_HALF_UP);// 4舍5入 | |||||
return src_v.doubleValue(); | |||||
} | |||||
/** | |||||
* 舍位处理,原生floor有坑,部分浮点数记录为.99999999999形式,导致floor结果错误 | |||||
* @param d | |||||
* @return | |||||
*/ | |||||
public static double floor(double d) { | |||||
return Math.floor(UtilMath.roundDouble(d, 2)); | |||||
} | |||||
/** | |||||
* 比较两Double是否相等,将会吧他们专程BigDecimal进行比较; | |||||
* | |||||
* @param src double1 | |||||
* @param tag double2 | |||||
* @return src > tag 返回1, src < tag 返回-1, 否则返回0 | |||||
*/ | |||||
public static int compare(double src, double tag) { | |||||
BigDecimal src_b = new BigDecimal(src); | |||||
BigDecimal src_v = src_b.divide(ONE_BIG, 2, BigDecimal.ROUND_HALF_UP);// 4舍5入 | |||||
BigDecimal tag_b = new BigDecimal(tag); | |||||
BigDecimal tag_v = tag_b.divide(ONE_BIG, 2, BigDecimal.ROUND_HALF_UP);// 4舍5入 | |||||
return src_v.compareTo(tag_v); | |||||
} | |||||
/** | |||||
* 自动过滤金额中的逗号转换为double,如果出错,则返回0 | |||||
* | |||||
* @param s 源串,可能为带逗号的金额串; | |||||
* @return double | |||||
*/ | |||||
public static Double toDouble(String s) { | |||||
return todouble(s); | |||||
} | |||||
/** | |||||
* 自动过滤金额中的逗号转换为double,如果出错,则返回0 | |||||
* | |||||
* @param s 源串,可能为带逗号的金额串; | |||||
* @return double | |||||
*/ | |||||
public static double todouble(String s) { | |||||
try { | |||||
return Double.parseDouble(s.replaceAll(",", "")); | |||||
} catch (Exception e) { | |||||
return 0.00; | |||||
} | |||||
} | |||||
/** | |||||
* 获取double,主要过滤d为null的情况; | |||||
* | |||||
* @param d Double对象; | |||||
* @return double | |||||
*/ | |||||
public static double todouble(Double d) { | |||||
if (d == null) return 0.0d; | |||||
return d.doubleValue(); | |||||
} | |||||
/** | |||||
* 自动过滤金额中的逗号转换为float,如果出错,则返回0 | |||||
* | |||||
* @param s 源串,可能为带逗号的金额串; | |||||
* @return Float | |||||
*/ | |||||
public static Float toFloat(String s) { | |||||
return tofloat(s); | |||||
} | |||||
/** | |||||
* 自动过滤金额中的逗号转换为float,如果出错,则返回0 | |||||
* | |||||
* @param s 源串,可能为带逗号的金额串; | |||||
* @return Float | |||||
*/ | |||||
public static float tofloat(String s) { | |||||
try { | |||||
return Float.parseFloat(s.replaceAll(",", "")); | |||||
} catch (Exception e) { | |||||
return 0.0f; | |||||
} | |||||
} | |||||
public static long tolong(String src, long defaultvalue) { | |||||
try { | |||||
return Long.parseLong(src); | |||||
} catch (Exception e) { | |||||
return defaultvalue; | |||||
} | |||||
} | |||||
public static int toint(String src, int defaultvalue) { | |||||
try { | |||||
return Integer.parseInt(src); | |||||
} catch (Exception e) { | |||||
return defaultvalue; | |||||
} | |||||
} | |||||
/** | |||||
* 考虑使用中的精度,判断一个Value是否>0,实际是>0.00001 | |||||
* | |||||
* @param value double类型 | |||||
* @return boolean | |||||
*/ | |||||
public static boolean isBigThanZero(double value) { | |||||
return (value > 0.00001); | |||||
} | |||||
/** | |||||
* 考虑使用中的精度,判断一个Value是否>0,实际是>0.00001 | |||||
* | |||||
* @param value String类型 | |||||
* @return boolean | |||||
*/ | |||||
public static boolean isBigThanZero(String value) { | |||||
return !PubUtil.isEmpty(value) && isBigThanZero(toDouble(value)); | |||||
} | |||||
/** | |||||
* 考虑使用中的精度,判断一个Value是否=0,实际是给出一个值范围。 | |||||
* | |||||
* @param value double类型 | |||||
* @return boolean | |||||
*/ | |||||
public static boolean isEqualsZero(double value) { | |||||
return (-0.00001 < value && value < 0.00001); | |||||
} | |||||
/** | |||||
* 考虑使用中的精度,判断一个Value是否=0,实际是给出一个值范围。 | |||||
* | |||||
* @param value String类型 | |||||
* @return boolean | |||||
*/ | |||||
public static boolean isEqualsZero(String value) { | |||||
return PubUtil.isEmpty(value) || isEqualsZero(toDouble(value)); | |||||
} | |||||
/** | |||||
* 是否是负数 | |||||
* | |||||
* @param db_val 要判断的double | |||||
* @return 负数则返回true; | |||||
*/ | |||||
public static boolean isNegative(double db_val) { | |||||
return (compare(db_val, 0.00D) == -1); | |||||
} | |||||
/** | |||||
* 是否是正数 | |||||
* | |||||
* @param db_val 要判断的double | |||||
* @return 正数则返回true; | |||||
*/ | |||||
public static boolean isPlus(double db_val) { | |||||
return (compare(db_val, 0.00D) == 1); | |||||
} | |||||
/** | |||||
* 得到金额字符串,保持小数点2位 | |||||
* | |||||
* @param db 将double转换为金额字符串; | |||||
* @return 金额字符串#0.00; | |||||
*/ | |||||
public static String toStdNumberString(double db) { | |||||
try { | |||||
return stdNumberFormat.format(db); | |||||
} catch (Exception e) { | |||||
return "0.00"; | |||||
} | |||||
} | |||||
public static String toStdNumberStringEx(double db) { | |||||
try { | |||||
if (compare(db, -1d) == 0) return "-"; | |||||
return stdNumberFormat.format(db); | |||||
} catch (Exception e) { | |||||
return "0.00"; | |||||
} | |||||
} | |||||
/** | |||||
* 将金额格式字符串,如23,333,093.01 去掉逗号 | |||||
* | |||||
* @param s 金额串 | |||||
* @return String 去掉逗号后的串,如果amount为空,则返回0.00 | |||||
*/ | |||||
public static String toStdNumberString(String s) { | |||||
if (PubUtil.isEmpty(s)) | |||||
return "0.00"; | |||||
return stdNumberFormat.format(UtilMath.todouble(s)); | |||||
} | |||||
/** | |||||
* 将数据转换为两位小数的数字格式; | |||||
* | |||||
* @param d 数据 | |||||
* @param isZeroToEmpty 如果未0,是否返回“”; | |||||
* @return 两位小数的字符串; | |||||
*/ | |||||
public static String toStdNumberString(double d, boolean isZeroToEmpty) { | |||||
if (isEqualsZero(d)) { | |||||
return isZeroToEmpty ? "": "0.00"; | |||||
} | |||||
return stdNumberFormat.format(d); | |||||
} | |||||
public static String toStdNumberString(String s, boolean isZeroToEmpty) { | |||||
return toStdNumberString(UtilMath.todouble(s), isZeroToEmpty); | |||||
} | |||||
public static String toStdNumberString(double d, int scale) { | |||||
DecimalFormat dfn = null; | |||||
if (scale == 1) dfn = df1Format; | |||||
if (scale == 2) dfn = df2Format; | |||||
else if (scale == 4) dfn = df4; | |||||
else if (scale == 6) dfn = df6NumberF; | |||||
else if (scale <= 0) dfn = dfLong; | |||||
else { | |||||
StringBuilder sb = new StringBuilder("###,###,###,###,##0."); | |||||
for (int i = 0; i < scale; i++) sb.append("0"); | |||||
dfn = new DecimalFormat(sb.toString()); | |||||
} | |||||
return dfn.format(d); | |||||
} | |||||
/** | |||||
* 将数字乘100,保留小数点后两位, 然后后面添加% | |||||
* | |||||
* @param d 值 | |||||
* @param isZeroToEmpty,如果值为0,是否返回空; | |||||
* @return 字符串; | |||||
*/ | |||||
public static String toStdPercentNumberStr(double d, boolean isZeroToEmpty) { | |||||
if (d > -0.00000000001 && d < 0.00000000001) { | |||||
return isZeroToEmpty ? "": "0.00%"; | |||||
} | |||||
return toStdNumberString(d * 100) + "%"; | |||||
} | |||||
public static String toStdAmountString(double d) { | |||||
return toStdAmountString(d, false); | |||||
} | |||||
/** | |||||
* 将数据转换为两位小数的金额格式,带逗号; | |||||
* | |||||
* @param d 数据 | |||||
* @param isZeroToEmpty 如果未0,是否返回“”; | |||||
* @return 金额格式的字符串; | |||||
*/ | |||||
public static String toStdAmountString(double d, boolean isZeroToEmpty) { | |||||
if (isEqualsZero(d)) { | |||||
return isZeroToEmpty ? "": "0.00"; | |||||
} | |||||
return stdAmountFormat.format(d); | |||||
} | |||||
public static String toStdAmountString(String s) { | |||||
return toStdAmountString(UtilMath.todouble(s), false); | |||||
} | |||||
public static String toStdAmountString(String s, boolean isZeroToEmpty) { | |||||
return toStdAmountString(UtilMath.todouble(s), isZeroToEmpty); | |||||
} | |||||
/** | |||||
* 将小写金额转换为人民币大写金额 | |||||
* | |||||
* @param s 金额格式的串 | |||||
* @return String 转换结果 | |||||
*/ | |||||
public static String toCapsAmountString(String s) { | |||||
if (PubUtil.isEmpty(s)) return ""; | |||||
return toCapsAmountString(todouble(s)); | |||||
} | |||||
/** | |||||
* 将小写金额转换为人民币大写金额 | |||||
* | |||||
* @param v double | |||||
* @return String 转换结果 | |||||
*/ | |||||
public static String toCapsAmountString(double v) { | |||||
if (v < MIN_VALUE || v > MAX_VALUE) return "参数非法!"; | |||||
boolean negative = isNegative(v); | |||||
if (negative) v = Math.abs(v); | |||||
long l = Math.round(v * 100); | |||||
if (l == 0) return "零元整"; | |||||
String strValue = String.valueOf(l); | |||||
// i用来控制数 | |||||
int i = 0; | |||||
// j用来控制单位 | |||||
int j = UNIT.length() - strValue.length(); | |||||
StringBuilder rs = new StringBuilder(32); | |||||
boolean isZero = false; | |||||
for (; i < strValue.length(); i++, j++) { | |||||
char ch = strValue.charAt(i); | |||||
if (ch == '0') { | |||||
isZero = true; | |||||
if (UNIT.charAt(j) == '亿' || UNIT.charAt(j) == '万' || UNIT.charAt(j) == '元') { | |||||
rs.append(UNIT.charAt(j)); | |||||
isZero = false; | |||||
} | |||||
} else { | |||||
if (isZero) { | |||||
rs.append('零'); | |||||
isZero = false; | |||||
} | |||||
rs.append(DIGIT.charAt(ch - '0')).append(UNIT.charAt(j)); | |||||
} | |||||
} | |||||
if (rs.charAt(rs.length() - 1) != '分') | |||||
rs.append('整'); | |||||
i = rs.indexOf("亿万"); | |||||
if (i > 0) rs.delete(i + 1, i + 2); // i+1 ->万 | |||||
if (negative) | |||||
return rs.insert(0, '负').toString(); | |||||
else | |||||
return rs.toString(); | |||||
} | |||||
/** | |||||
* 返回0 到 maxvalue的随机数 | |||||
* | |||||
* @param maxvalue 随机数的最大值 | |||||
* @return int | |||||
*/ | |||||
public static int rnd(int maxvalue) { | |||||
return (int) (Math.random() * (maxvalue + 1)); | |||||
} | |||||
public static double chkDbNull(Double v) { | |||||
return v == null ? 0: v; | |||||
} | |||||
public static double max(double d1, double d2) { | |||||
return compare(d1, d2) < 0 ? d2 : d1; | |||||
} | |||||
public static double min(double d1, double d2) { | |||||
return compare(d1, d2) < 0 ? d1 : d2; | |||||
} | |||||
public static void main(String[] args) { | |||||
double aa=123456789.345678900005; | |||||
System.out.println("args0 = " + upDouble(aa,0)); | |||||
System.out.println("args1 = " + upDouble(aa,1)); | |||||
System.out.println("args2 = " + upDouble(aa,2)); | |||||
System.out.println("args3 = " + upDouble(aa,3)); | |||||
System.out.println("args4 = " + upDouble(aa,4)); | |||||
System.out.println("args5 = " + upDouble(aa,5)); | |||||
System.out.println("args5 = " + upDouble(aa,6)); | |||||
System.out.println("args5 = " + upDouble(aa,7)); | |||||
System.out.println("args5 = " + upDouble(aa,8)); | |||||
} | |||||
/** | |||||
* double 去尾法 | |||||
* @param src 待处理数据 | |||||
* @param scale 保留小数位数 | |||||
* @return | |||||
*/ | |||||
public static double cutDouble(double src, int scale){ | |||||
String v = toStdNumberString(src, 6);//先到6位小数,再去计算,否则容易出错,如8.3成8.29999999999,舍位就成了8.29了 | |||||
DecimalFormat formater = new DecimalFormat(); | |||||
formater.setMaximumFractionDigits(scale); | |||||
formater.setGroupingSize(0); | |||||
formater.setRoundingMode(RoundingMode.FLOOR); | |||||
return new BigDecimal(formater.format(toDouble(v))).doubleValue(); | |||||
} | |||||
/** | |||||
* double 进位法 | |||||
* @param src 待处理数据 | |||||
* @param scale 保留小数位数 | |||||
* @return | |||||
*/ | |||||
public static double upDouble(double src, int scale){ | |||||
String v = toStdNumberString(src, 6);//先到6位小数,再去计算 | |||||
DecimalFormat formater = new DecimalFormat(); | |||||
formater.setMaximumFractionDigits(scale); | |||||
formater.setGroupingSize(0); | |||||
formater.setRoundingMode(RoundingMode.UP); | |||||
return new BigDecimal(formater.format(toDouble(v))).doubleValue(); | |||||
} | |||||
} |
@@ -0,0 +1,504 @@ | |||||
package cc.smtweb.system.bpm.util; | |||||
import cc.smtweb.framework.core.util.PubUtil; | |||||
import java.text.Collator; | |||||
import java.util.*; | |||||
/** | |||||
* Created with IntelliJ IDEA. | |||||
* User: AKhh | |||||
* Date: 12-12-24 下午5:09 | |||||
* To change this template use File | Settings | File Templates. | |||||
*/ | |||||
@SuppressWarnings("UnusedDeclaration") | |||||
public class UtilString { | |||||
private static Collator chineseCollator = Collator.getInstance(Locale.CHINA); | |||||
/** | |||||
* strSrc中寻找第一个strSe并且返回以其分隔的Left部分,汉字长度也为1 | |||||
* | |||||
* @param strSrc 源字符串 | |||||
* @param strSe 分割字符 | |||||
* @return String 返回 | |||||
*/ | |||||
public static String getLeft(String strSrc, String strSe) { | |||||
if (PubUtil.isEmpty(strSrc)) | |||||
return ""; | |||||
if (PubUtil.isEmpty(strSe)) | |||||
strSe = " "; | |||||
String result = ""; | |||||
int pos = strSrc.indexOf(strSe); | |||||
if (pos >= 0) | |||||
result = strSrc.substring(0, pos); | |||||
return result; | |||||
} | |||||
/** | |||||
* 返回字符串的左边部分,汉字长度也为1 | |||||
* | |||||
* @param strSrc 源串,如果为空,则返回“”; | |||||
* @param count 要获取的右边字符串长度,负数将返回“”,如果count>字符串长度,则返回整个字符串; | |||||
* @return String return | |||||
*/ | |||||
public static String getLeft(String strSrc, int count) { | |||||
if (PubUtil.isEmpty(strSrc) || count <= 0) { | |||||
return ""; | |||||
} | |||||
if (strSrc.length() < count) { | |||||
return strSrc; | |||||
} else { | |||||
return strSrc.substring(0, count); | |||||
} | |||||
} | |||||
/** | |||||
* strSrc中寻找第一个strSe并且返回以其分隔的Right部分,汉字长度也为1 | |||||
* | |||||
* @param strSrc 源串 | |||||
* @param strSe 分隔符,一个字符 | |||||
* @return String right部分 | |||||
*/ | |||||
public static String getRight(String strSrc, String strSe) { | |||||
if (PubUtil.isEmpty(strSrc)) | |||||
return ""; | |||||
if (PubUtil.isEmpty(strSe)) | |||||
strSe = " "; | |||||
String result = strSrc; | |||||
int pos = strSrc.indexOf(strSe); | |||||
if (pos >= 0) | |||||
result = strSrc.substring(pos + strSe.length()); | |||||
return result; | |||||
} | |||||
/** | |||||
* 返回字符串的右边部分,汉字长度也为1 | |||||
* | |||||
* @param strSrc 源串 | |||||
* @param count 要获取的右边字符串长度,负数将返回“”,如果count>字符串长度,则返回整个字符串; | |||||
* @return String return | |||||
*/ | |||||
public static String getRight(String strSrc, int count) { | |||||
if (PubUtil.isEmpty(strSrc) || count <= 0) { | |||||
return ""; | |||||
} | |||||
int l = strSrc.length(); | |||||
if (l <= count) { | |||||
return strSrc; | |||||
} | |||||
return strSrc.substring(l - count); | |||||
} | |||||
/** | |||||
* 左边补齐字符 | |||||
* | |||||
* @param src 源串 | |||||
* @param pad 补齐字符 | |||||
* @param length 最终长度 | |||||
* @return 补齐后的字符串 | |||||
*/ | |||||
public static String padLeft(String src, String pad, int length) { | |||||
StringBuilder sb = new StringBuilder(repeatString(pad, length)); | |||||
sb.append(src); | |||||
return sb.substring(sb.length() - length); | |||||
} | |||||
public static String padLeft(long src, String pad, int length) { | |||||
StringBuilder sb = new StringBuilder(repeatString(pad, length)); | |||||
sb.append(src); | |||||
return sb.substring(sb.length() - length); | |||||
} | |||||
public static String padRight(String src, String pad, int length) { | |||||
StringBuilder sb = new StringBuilder(length * pad.length() + src.length()); | |||||
sb.append(src).append(repeatString(pad, length)); | |||||
return sb.substring(0, length); | |||||
} | |||||
public static String padRight(long src, String pad, int length) { | |||||
StringBuilder sb = new StringBuilder(length * pad.length()); | |||||
sb.append(src).append(repeatString(pad, length)); | |||||
return sb.substring(0, length); | |||||
} | |||||
/** | |||||
* 由于jdk1.3提供的replace函数不能满足替换要求,自己写一个 | |||||
* | |||||
* @param src 源串 | |||||
* @param oldS 将... | |||||
* @param newS 替换成... | |||||
* @return 替换后的字符串 | |||||
*/ | |||||
public static String replaceString(String src, String oldS, String newS) { | |||||
StringBuilder ret = new StringBuilder(64); | |||||
int pos = src.indexOf(oldS); | |||||
while (pos >= 0) { | |||||
ret.append(src, 0, pos).append(newS); | |||||
src = src.substring(pos + oldS.length()); | |||||
pos = src.indexOf(oldS); | |||||
} | |||||
ret.append(src); | |||||
return ret.toString(); | |||||
} | |||||
/** | |||||
* 取得指定字符串左边的有效数字,首先去掉两边空格 | |||||
* | |||||
* @param s 源串 | |||||
* @return 串左边的有效数字 | |||||
*/ | |||||
public static String getStringLeftNumber(String s) { | |||||
String ret = ""; | |||||
int dotCount = 0; | |||||
s = s.trim(); | |||||
char[] carr = s.toCharArray(); | |||||
for (char aCarr : carr) { | |||||
if (Character.isDigit(aCarr)) { | |||||
ret += aCarr; | |||||
} else if (aCarr == '.' && dotCount == 0) { | |||||
ret += aCarr; | |||||
dotCount++; | |||||
} else { | |||||
break; | |||||
} | |||||
} | |||||
if (ret.endsWith(".")) { | |||||
ret = ret.substring(0, ret.length() - 1); | |||||
} | |||||
return ret; | |||||
} | |||||
/** | |||||
* 取得重复字串 | |||||
* | |||||
* @param repeatString 重复字串 | |||||
* @param count 重复次数 | |||||
* @return String | |||||
*/ | |||||
public static String repeatString(String repeatString, int count) { | |||||
if (count <= 0) return ""; | |||||
StringBuilder ret = new StringBuilder(repeatString.length() * count); | |||||
for (int i = 1; i <= count; i++) { | |||||
ret.append(repeatString); | |||||
} | |||||
return ret.toString(); | |||||
} | |||||
/** | |||||
* 去除字符串左边的指定字符串 | |||||
* | |||||
* @param src 源字符串 | |||||
* @param cut 要去掉的字符串; | |||||
* @return 处理结果 | |||||
*/ | |||||
public static String cutStringLeft(String src, String cut) { | |||||
if (PubUtil.isEmpty(src) || PubUtil.isEmpty(cut)) { | |||||
return ""; | |||||
} | |||||
if (src.startsWith(cut)) { | |||||
return cutStringLeft(src.substring(cut.length()), cut); | |||||
} else { | |||||
return src; | |||||
} | |||||
} | |||||
public static String cutStringRight(String src, String cut) { | |||||
if (PubUtil.isEmpty(src) || PubUtil.isEmpty(cut)) { | |||||
return ""; | |||||
} | |||||
while (src.endsWith(cut)) | |||||
src = src.substring(0, src.length() - cut.length()); | |||||
return src; | |||||
} | |||||
/** | |||||
* Removes all spaces from a string | |||||
* 可以替换大部分空白字符, 不限于空格,\s 可以匹配空格、制表符、换页符等空白字符的其中任意一个 | |||||
*/ | |||||
public static String removeSpaces(String str) { | |||||
return str.replaceAll("\\s*", ""); | |||||
} | |||||
/** | |||||
* Creates a single string from a List of strings seperated by a delimiter. | |||||
* | |||||
* @param list a list of strings to join | |||||
* @param delim the delimiter character(s) to use. (null value will join with no delimiter) | |||||
* @return a String of all values in the list seperated by the delimiter | |||||
*/ | |||||
public static String join(List<String> list, String delim) { | |||||
if (list == null || list.size() < 1) | |||||
return null; | |||||
StringBuffer buf = new StringBuffer(); | |||||
Iterator i = list.iterator(); | |||||
while (i.hasNext()) { | |||||
buf.append((String) i.next()); | |||||
if (i.hasNext()) | |||||
buf.append(delim); | |||||
} | |||||
return buf.toString(); | |||||
} | |||||
/** | |||||
* Splits a String on a delimiter into a List of Strings. | |||||
* | |||||
* @param str the String to split | |||||
* @param delim the delimiter character(s) to join on (null will split on whitespace) | |||||
* @return a list of Strings | |||||
*/ | |||||
public static List<String> split(String str, String delim) { | |||||
List<String> splitList = new ArrayList<>(); | |||||
StringTokenizer st; | |||||
if (str == null) | |||||
return splitList; | |||||
if (delim != null) | |||||
st = new StringTokenizer(str, delim); | |||||
else | |||||
st = new StringTokenizer(str); | |||||
while (st.hasMoreTokens()) { | |||||
splitList.add(st.nextToken()); | |||||
} | |||||
return splitList; | |||||
} | |||||
//是否为true,(1,y,true,yes) | |||||
public static boolean toBoolean(String v) { | |||||
return "1".equals(v) || "y".equalsIgnoreCase(v) || "true".equalsIgnoreCase(v) || "yes".equalsIgnoreCase(v); | |||||
} | |||||
public static int chineseCompare(String s1, String s2) { | |||||
return chineseCollator.compare(s1, s2); | |||||
} | |||||
/** | |||||
* 按照编码级次,得到类型的真实编码,主要用于like 'parentCode%' | |||||
* getSplitTypeCode('GF82000',2, 2, 1) == GF82 | |||||
* getSplitTypeCode('GF82100',3, 2, 1) == GF821 | |||||
* getSplitTypeCode('82100' ,3, 0, 1) == 821 | |||||
* | |||||
* @param curLevel 当前编码的所在层次 | |||||
* @param startIndex 数字编码的开始选项 | |||||
* @param perSize 每层的数字编码长度 | |||||
*/ | |||||
public static String getRealCode(String code, int curLevel, int startIndex, int perSize) { | |||||
StringBuilder sb = new StringBuilder(code.length()); | |||||
if (startIndex > 0) sb.append(code, 0, startIndex); | |||||
for (int i = startIndex, l = 0; i < code.length(); i += perSize) { | |||||
if (l < curLevel) { | |||||
sb.append(code, i, i + perSize); | |||||
++l; | |||||
} else { | |||||
break; | |||||
} | |||||
} | |||||
return sb.toString(); | |||||
} | |||||
//函数功能: 正整数 | |||||
public static boolean isPureNumber(String inputString) { | |||||
return inputString.matches("^[1-9]\\d*$"); | |||||
} | |||||
//函数功能: 整数 | |||||
public static boolean isNumber(String inputString) { | |||||
return inputString.matches("^[-+][0-9]\\d*$"); | |||||
} | |||||
//函数功能: 浮点数 | |||||
public static boolean isAmount(String inputString) { | |||||
return inputString.matches("^[-+]?[\\d,]+(\\.\\d+)?$"); | |||||
} | |||||
//函数功能: 带千分号的整数 | |||||
public static boolean isFormatNumber(String inputString) { | |||||
return inputString.matches("^[-+]?[\\d,]+(\\d+)?$"); | |||||
} | |||||
//首字母大写 | |||||
public static String upFirst(String s) { | |||||
return s.substring(0, 1).toUpperCase() + s.substring(1); | |||||
} | |||||
public static String padRightBytes(String src, String pad, int length) { | |||||
length -= src.replaceAll("[^\\x00-\\xff]", "**").length(); | |||||
return src + repeatString(pad, length); | |||||
} | |||||
//按字节数取子串,begin不是按字节的 | |||||
public static String substrByte(String src, int begin, int len) { | |||||
StringBuilder sb = new StringBuilder(32); | |||||
char c; | |||||
int tl = src.length(); | |||||
for (int i = begin; i < len + begin && i < tl; i++) { | |||||
c = src.charAt(i); | |||||
sb.append(c); | |||||
if (String.valueOf(c).replaceAll("[^\\x00-\\xff]", "**").length() > 1) { | |||||
// 遇到中文汉字,截取字节总数减1 | |||||
--len; | |||||
} | |||||
} | |||||
return sb.toString(); | |||||
} | |||||
/** | |||||
* 通配符算法。 可以匹配"*"和"?" | |||||
* 如a*b?d可以匹配aAAAbcd | |||||
* | |||||
* @param pattern 匹配表达式 | |||||
* @param str 匹配的字符串 | |||||
* @return | |||||
*/ | |||||
public static boolean match(String pattern, String str) { | |||||
if (pattern == null || str == null) | |||||
return false; | |||||
boolean result = false; | |||||
char c; // 当前要匹配的字符串 | |||||
boolean beforeStar = false; // 是否遇到通配符* | |||||
int back_i = 0;// 回溯,当遇到通配符时,匹配不成功则回溯 | |||||
int back_j = 0; | |||||
int i, j; | |||||
for (i = 0, j = 0; i < str.length(); ) { | |||||
if (pattern.length() <= j) { | |||||
if (back_i != 0) {// 有通配符,但是匹配未成功,回溯 | |||||
beforeStar = true; | |||||
i = back_i; | |||||
j = back_j; | |||||
back_i = 0; | |||||
back_j = 0; | |||||
continue; | |||||
} | |||||
break; | |||||
} | |||||
if ((c = pattern.charAt(j)) == '*') { | |||||
if (j == pattern.length() - 1) {// 通配符已经在末尾,返回true | |||||
result = true; | |||||
break; | |||||
} | |||||
beforeStar = true; | |||||
j++; | |||||
continue; | |||||
} | |||||
if (beforeStar) { | |||||
if (str.charAt(i) == c) { | |||||
beforeStar = false; | |||||
back_i = i + 1; | |||||
back_j = j; | |||||
j++; | |||||
} | |||||
} else { | |||||
if (c != '?' && c != str.charAt(i)) { | |||||
result = false; | |||||
if (back_i != 0) {// 有通配符,但是匹配未成功,回溯 | |||||
beforeStar = true; | |||||
i = back_i; | |||||
j = back_j; | |||||
back_i = 0; | |||||
back_j = 0; | |||||
continue; | |||||
} | |||||
break; | |||||
} | |||||
j++; | |||||
} | |||||
i++; | |||||
} | |||||
if (i == str.length() && j == pattern.length())// 全部遍历完毕 | |||||
result = true; | |||||
return result; | |||||
} | |||||
//填充变量 | |||||
public static String myReplaceStrEx(String express, String b, String e, IStrHanlder hanlder) { | |||||
if (null == express) return express; | |||||
int keyBegin = 0, keyEnd = 0; | |||||
int lb = b.length(), le = e.length(); | |||||
String fn; | |||||
while (true) { | |||||
keyBegin = express.indexOf(b, keyBegin); | |||||
if (keyBegin < 0) break; | |||||
keyEnd = express.indexOf(e, keyBegin); | |||||
if (keyEnd <= keyBegin) break; | |||||
keyBegin++; | |||||
fn = express.substring(keyBegin + lb - 1, keyEnd); | |||||
fn = hanlder.work(fn); | |||||
if (fn != null) { | |||||
express = express.substring(0, keyBegin - 1) + fn + express.substring(keyEnd + le); | |||||
} | |||||
} | |||||
return express; | |||||
} | |||||
//填充变量 | |||||
public static String myReplaceStrEx(String express, String b, String e, final Map<String, String> mapVals) { | |||||
return myReplaceStrEx(express, b, e, new IStrHanlder() { | |||||
@Override | |||||
public String work(String src) { | |||||
return PubUtil.checkNull(mapVals.get(src)); | |||||
} | |||||
}); | |||||
} | |||||
/*Blob转String*/ | |||||
// public static String blob2Str(Blob blob) { | |||||
// if (blob == null) return ""; | |||||
// ByteArrayOutputStream outStream = null; | |||||
// try { | |||||
// long len = blob.length(); | |||||
// if (len == 0L) return ""; | |||||
// byte[] bytes; | |||||
// long i = 1L; | |||||
// outStream = new ByteArrayOutputStream(); | |||||
// while (i < len) { | |||||
// bytes = blob.getBytes(i, 1024); | |||||
// i += 1024L; | |||||
// outStream.write(bytes); | |||||
// } | |||||
// | |||||
// return UtilEncode.base64EncodeB(outStream.toByteArray()); | |||||
// } catch (Exception e) { | |||||
// e.printStackTrace(); | |||||
// return ""; | |||||
// } finally { | |||||
// IOUtils.closeQuietly(outStream); | |||||
// } | |||||
// } | |||||
public interface IStrHanlder { | |||||
String work(String src); | |||||
} | |||||
public static int[] splitStr(String src, String ch) { | |||||
String[] ss = src.split(ch); | |||||
int[] ret = new int[ss.length]; | |||||
for (int i = 0, len = ss.length; i < len; i++) { | |||||
ret[i] = PubUtil.getIntIgnoreErr(ss[i]); | |||||
} | |||||
return ret; | |||||
} | |||||
public static void main(String[] args) { | |||||
String s = "a[#[#123#]bcde[aaa]bcd"; | |||||
s = UtilString.myReplaceStrEx(s, "[#", "#]", new UtilString.IStrHanlder() { | |||||
@Override | |||||
public String work(String src) { | |||||
if (src.equals("123")) return "1"; | |||||
return null; | |||||
} | |||||
}); | |||||
System.out.println(s); | |||||
} | |||||
} |
@@ -0,0 +1,6 @@ | |||||
package cc.smtweb.system.bpm.util.ftp; | |||||
//FTP执行接口 | |||||
public interface FtpTask { | |||||
Object execute(IFtpUtil ftp) throws Exception; | |||||
} |
@@ -0,0 +1,255 @@ | |||||
package cc.smtweb.system.bpm.util.ftp; | |||||
import cc.smtweb.framework.core.util.DateUtil; | |||||
import cc.smtweb.framework.core.util.PubUtil; | |||||
import cc.smtweb.system.bpm.util.UtilLogger; | |||||
import java.io.File; | |||||
import java.util.ArrayList; | |||||
import java.util.HashMap; | |||||
import java.util.List; | |||||
import java.util.Map; | |||||
//ftp管理类 | |||||
public class FtpTaskManager { | |||||
private static Map<String, FtpTaskManager> mapInstance = null; | |||||
static { | |||||
mapInstance = new HashMap<>(); | |||||
} | |||||
//多线程 | |||||
private Map<Thread, IFtpUtil> mapThreadFtp = new HashMap<>(); | |||||
public static FtpTaskManager getInstance(String key, IFtpServerConfig ftpConfig) { | |||||
key = key + "_" + (ftpConfig.isSFTP() ? 1 : 0) + ftpConfig.getServerIp() + "_" + ftpConfig.getPort() + "_" + ftpConfig.getUserName(); | |||||
FtpTaskManager instance = mapInstance.get(key); | |||||
if (instance == null) { | |||||
synchronized (FtpTaskManager.class) { | |||||
instance = mapInstance.get(key); | |||||
if (instance == null) { | |||||
FtpTaskManager inst = new FtpTaskManager(); | |||||
inst.init(ftpConfig); | |||||
instance = inst; | |||||
mapInstance.put(key, instance); | |||||
} | |||||
} | |||||
} | |||||
return instance; | |||||
} | |||||
private IFtpServerConfig ftpConfig = null; | |||||
public FtpTaskManager() { | |||||
} | |||||
//初始化配置信息 | |||||
public void init(IFtpServerConfig ftpConfig) { | |||||
this.ftpConfig = ftpConfig; | |||||
} | |||||
//获取一个ftp客户端 | |||||
public IFtpUtil getFtpUtil() { | |||||
IFtpUtil ftp = mapThreadFtp.get(Thread.currentThread()); | |||||
if (ftp != null) return ftp; | |||||
ftp = ftpConfig.isSFTP() ? new SFtpUtil() : new FtpUtil(); | |||||
boolean isConnect = ftp.login(ftpConfig); | |||||
if (isConnect) { | |||||
UtilLogger.info("FTP连接成功!"); | |||||
} else { | |||||
UtilLogger.info("FTP连接失败!" + ftpConfig.getServerIp() + " " + ftpConfig.getPort() + " " + ftpConfig.getUserName() + " " + ftpConfig.getPassword()); | |||||
} | |||||
return ftp; | |||||
} | |||||
//获取并加到线程中备用 | |||||
public IFtpUtil getThreadFtpUtil() { | |||||
IFtpUtil ftp = getFtpUtil(); | |||||
ftp.setAutoFree(false); | |||||
mapThreadFtp.put(Thread.currentThread(), ftp); | |||||
return ftp; | |||||
} | |||||
//释放,和getThreadFtpUtil配对 | |||||
public void dispose() { | |||||
IFtpUtil ftp = mapThreadFtp.remove(Thread.currentThread()); | |||||
if (ftp == null) return; | |||||
ftp.setAutoFree(true); | |||||
ftp.disconnect(); | |||||
} | |||||
/** | |||||
* 直接执行一个Ftp任务 | |||||
*/ | |||||
public Object execute(FtpTask ftpTask) throws Exception { | |||||
IFtpUtil ftp = getFtpUtil(); | |||||
if (!ftp.isConnected()) | |||||
throw new Exception("FTP连接失败(" + ftpConfig.getServerIp() + "/" + ftpConfig.getUserName() + "/" + (ftpConfig.isSFTP() ? "sftp" : "ftp") + ")。"); | |||||
try { | |||||
return ftpTask.execute(ftp); | |||||
} finally { | |||||
ftp.disconnect(); | |||||
} | |||||
} | |||||
//上传文件到Ftp服务器。传完后,根据设置删除本地文件 | |||||
public void uploadToFtp(final String remoteAttachName, | |||||
final String remoteFolderPath, final String localAttach, | |||||
final boolean isDelLocal) throws Exception { | |||||
uploadToFtp(remoteAttachName, remoteFolderPath, new File(localAttach), isDelLocal); | |||||
} | |||||
public void uploadToFtp(final String remoteAttachName, | |||||
final String remoteFolderPath, final File localFile, | |||||
final boolean isDelLocal) throws Exception { | |||||
this.execute(new FtpTask() { | |||||
public Object execute(IFtpUtil ftp) throws Exception { | |||||
if (ftp.uploadFile(remoteFolderPath, remoteAttachName, localFile)) { | |||||
if (isDelLocal) {//删除本地服务器的相应附件 | |||||
localFile.delete(); | |||||
} | |||||
} | |||||
return null; | |||||
} | |||||
}); | |||||
} | |||||
private String getBakPath(String path) { | |||||
path = PubUtil.isEmpty(path) ? DateUtil.getNowYm() : path; | |||||
return "bak/" + path + "/"; | |||||
} | |||||
//上传文件到Ftp服务器。传完后,根据设置删除本地文件 | |||||
public void downloadFile(final String remoteAttachName, | |||||
final String remoteFolderPath, final String localFile, final boolean isDelLocal) throws Exception { | |||||
this.execute(new FtpTask() { | |||||
public Object execute(IFtpUtil ftp) throws Exception { | |||||
if (!ftp.existsFile(remoteFolderPath, remoteAttachName)) { | |||||
throw new Exception("服务器文件【" + remoteFolderPath + "/" + remoteAttachName + "】不存在!"); | |||||
} | |||||
ftp.downloadFileEx(remoteFolderPath, remoteAttachName, localFile); | |||||
if (isDelLocal) { | |||||
ftp.setRemoteDir("/"); | |||||
final String bakPath = getBakPath(null); | |||||
ftp.mkdir(remoteFolderPath + "/" + bakPath); | |||||
ftp.rename(remoteFolderPath, remoteAttachName, bakPath + remoteAttachName); | |||||
} | |||||
return null; | |||||
} | |||||
}); | |||||
} | |||||
public void delAndBakFile(String remoteFolderPath, String remoteAttachName) throws Exception { | |||||
delAndBakFile(remoteFolderPath, remoteAttachName, null); | |||||
} | |||||
public void delAndBakFile(String remoteFolderPath, String remoteAttachName, String bakPath) throws Exception { | |||||
this.execute(new FtpTask() { | |||||
public Object execute(IFtpUtil ftp) throws Exception { | |||||
if (!ftp.existsFile(remoteFolderPath, remoteAttachName)) return null; | |||||
String path = getBakPath(bakPath); | |||||
ftp.setRemoteDir("/"); | |||||
ftp.mkdir(remoteFolderPath + "/" + path); | |||||
ftp.rename(remoteFolderPath, remoteAttachName, path + remoteAttachName); | |||||
return null; | |||||
} | |||||
}); | |||||
} | |||||
public void delFile(String delPath, String fileName) throws Exception { | |||||
this.execute(new FtpTask() { | |||||
public Object execute(IFtpUtil ftp) throws Exception { | |||||
if (!ftp.existsFile(delPath, fileName)) return null; | |||||
ftp.deleteFile(delPath,fileName ); | |||||
return null; | |||||
} | |||||
}); | |||||
} | |||||
//从服务器下载文件到本地。传完后,根据设置删除远程目录文件 | |||||
public String[] listFileNames(final String remotePath) throws Exception { | |||||
IFtpUtil ftp = getFtpUtil(); | |||||
if (!ftp.isConnected()) return new String[0]; | |||||
String[] fileNames; | |||||
try { | |||||
fileNames = ftp.listFileNames(remotePath); | |||||
} finally { | |||||
ftp.disconnect(); | |||||
} | |||||
return fileNames; | |||||
} | |||||
public String[] downFolder(final String remotePath, final String localPath, final boolean isDelLocal, final IDownloadFileWorker worker, final String fileNamePrefix) throws Exception { | |||||
final String[] files = listFileNames(remotePath); | |||||
List<String> list = new ArrayList<>(); | |||||
this.execute(new FtpTask() { | |||||
public Object execute(IFtpUtil ftp) throws Exception { | |||||
for (String file : files) { | |||||
if (worker != null && !worker.isDownload(file, fileNamePrefix)) continue; | |||||
if (PubUtil.isNotEmptyId(fileNamePrefix) && !file.startsWith(fileNamePrefix)) continue; | |||||
ftp.downloadFileEx(remotePath, file, localPath + "/" + file); | |||||
if (isDelLocal) { | |||||
ftp.setRemoteDir("/"); | |||||
final String bakPath = getBakPath(null); | |||||
ftp.mkdir(remotePath + "/" + bakPath); | |||||
ftp.rename(remotePath, file, bakPath + file); | |||||
} | |||||
list.add(file); | |||||
} | |||||
return null; | |||||
} | |||||
}); | |||||
return list.toArray(new String[list.size()]); | |||||
} | |||||
public static void main(String[] args) throws Exception { | |||||
FtpTaskManager ftp = FtpTaskManager.getInstance("test", new IFtpServerConfig() { | |||||
@Override | |||||
public boolean isSFTP() { | |||||
return false; | |||||
} | |||||
@Override | |||||
public String getServerIp() { | |||||
return "127.0.0.1"; | |||||
} | |||||
@Override | |||||
public Integer getPort() { | |||||
return 21; | |||||
} | |||||
@Override | |||||
public String getUserName() { | |||||
return "demo"; | |||||
} | |||||
@Override | |||||
public String getPassword() { | |||||
return "1"; | |||||
} | |||||
}); | |||||
ftp.uploadToFtp("S_2.jpg", "/", "f:\\temp\\tmp\\S_2.jpg", false); | |||||
// ftp.uploadToFtp("民族5.png", "/", "f:\\temp\\temp\\民族5.png", false); | |||||
// ftp.getThreadFtpUtil(); | |||||
// ftp.uploadToFtp("民族1.png", "/", "f:\\temp\\temp\\民族1.png", false); | |||||
// ftp.uploadToFtp("民族2.png", "/", "f:\\temp\\temp\\民族2.png", false); | |||||
// ftp.uploadToFtp("民族3.png", "/", "f:\\temp\\temp\\民族3.png", false); | |||||
// ftp.downloadFile("民族2.png", "/", "f:/temp/民族2.png", true); | |||||
/*String[] ss = ftp.downFolder("/", "f:/temp/test", true); | |||||
for (String s: ss) { | |||||
System.out.println(s); | |||||
}*/ | |||||
ftp.downloadFile("S_1.jpg", "/", "f:/temp/S_21.jpg", true); | |||||
// ftp.downloadFile("freesshd.log", "/", "f:/temp/freesshd.log", false); | |||||
//ftp.downFolder("data/11", "f:/temp/11", true, ""); | |||||
ftp.dispose(); | |||||
} | |||||
} |
@@ -0,0 +1,393 @@ | |||||
package cc.smtweb.system.bpm.util.ftp; | |||||
import cc.smtweb.framework.core.util.PubUtil; | |||||
import cc.smtweb.system.bpm.util.UtilFile; | |||||
import cc.smtweb.system.bpm.util.UtilLogger; | |||||
import org.apache.commons.net.ftp.FTPClient; | |||||
import org.apache.commons.net.ftp.FTPFile; | |||||
import org.apache.commons.net.ftp.FTPReply; | |||||
import java.io.*; | |||||
import java.net.UnknownHostException; | |||||
import java.nio.charset.StandardCharsets; | |||||
import java.util.ArrayList; | |||||
import java.util.List; | |||||
/** | |||||
* 一个ftp的封装类 | |||||
*/ | |||||
@SuppressWarnings("UnusedDeclaration") | |||||
public class FtpUtil implements IFtpUtil { | |||||
private static final int LOGIN_REPEAT_TIMES = 1; | |||||
private FTPClient ftpClient; | |||||
private boolean autoFree = true; | |||||
private IFtpServerConfig ftpConf; | |||||
public FtpUtil() { | |||||
this.ftpClient = new FTPClient(); | |||||
} | |||||
@Override | |||||
public boolean isAutoFree() { | |||||
return autoFree; | |||||
} | |||||
@Override | |||||
public void setAutoFree(boolean autoFree) { | |||||
this.autoFree = autoFree; | |||||
} | |||||
//登录ftp | |||||
@Override | |||||
public boolean login(IFtpServerConfig ftpConf) { | |||||
try { | |||||
this.ftpConf = ftpConf; | |||||
return login(ftpConf.getServerIp(), ftpConf.getPort(), ftpConf.getUserName(), ftpConf.getPassword()); | |||||
} catch (Exception e) { | |||||
logError("ftp登录失败", e); | |||||
return false; | |||||
} | |||||
} | |||||
//退出ftp | |||||
@Override | |||||
public void logout() { | |||||
try { | |||||
if (ftpClient.isConnected()) { | |||||
ftpClient.logout(); | |||||
} | |||||
} catch (IOException e) { | |||||
logError("ftp退出登录失败", e); | |||||
} | |||||
} | |||||
//是否连接正常 | |||||
@Override | |||||
public boolean isConnected() { | |||||
if (!ftpClient.isConnected()) | |||||
return false; | |||||
try { | |||||
return ftpClient.sendNoOp(); | |||||
} catch (IOException e) { | |||||
logError("ftp测试连接失败", e); | |||||
return false; | |||||
} | |||||
} | |||||
//设置远程目录 | |||||
@Override | |||||
public boolean setRemoteDir(String path) { | |||||
try { | |||||
String d = gbktoiso8859(path); | |||||
ftpClient.changeWorkingDirectory("/"); | |||||
if (!ftpClient.changeWorkingDirectory(d)) { | |||||
String[] paths = d.split("/"); | |||||
for (String pa : paths) { | |||||
if (!ftpClient.changeWorkingDirectory(pa)) { | |||||
ftpClient.mkd(pa); | |||||
ftpClient.changeWorkingDirectory(pa); | |||||
} | |||||
} | |||||
} | |||||
return true; | |||||
} catch (IOException e) { | |||||
logError("ftp设置远程目录失败", e); | |||||
return false; | |||||
} | |||||
} | |||||
/** | |||||
* 创建指定文件夹 | |||||
* | |||||
* @param dirName dirName | |||||
*/ | |||||
public void mkdir(String dirName) { | |||||
setRemoteDir("/"); | |||||
dirName = gbktoiso8859(dirName); | |||||
try { | |||||
ftpClient.makeDirectory(dirName); | |||||
} catch (Exception e) { | |||||
logError("ftp创建远程目录错误", e); | |||||
} | |||||
} | |||||
//删除远程路径 | |||||
@Override | |||||
public void deleteFolder(String path) { | |||||
try { | |||||
String d = gbktoiso8859(path); | |||||
ftpClient.removeDirectory(d); | |||||
} catch (IOException e) { | |||||
logError("ftp删除远程目录失败", e); | |||||
} | |||||
} | |||||
/** | |||||
* 从ftp下载文件到本地 | |||||
* | |||||
* @param remotePath 远程路径 | |||||
* @param fileName 文件名 | |||||
* @param localPath 本地路径(不带文件名) | |||||
*/ | |||||
@Override | |||||
public void downloadFile(String remotePath, String fileName, String localPath) throws Exception { | |||||
downloadFileEx(remotePath, fileName, localPath + File.separator + fileName); | |||||
} | |||||
public void setPassiveNatWorkaroundStrategy() { | |||||
ftpClient.setPassiveNatWorkaroundStrategy(new FTPClient.HostnameResolver() { | |||||
@Override | |||||
public String resolve(String hostname) throws UnknownHostException { | |||||
return ftpConf.getServerIp(); | |||||
} | |||||
}); | |||||
} | |||||
/** | |||||
* 下载文件到本地 | |||||
* | |||||
* @param remotePath 远程路径 | |||||
* @param fileName 远程文件名 | |||||
* @param localFileName 本地完全文件名(路径+文件名) | |||||
*/ | |||||
@Override | |||||
public void downloadFileEx(String remotePath, String fileName, String localFileName) throws Exception { | |||||
setPassiveNatWorkaroundStrategy(); | |||||
ftpClient.enterLocalPassiveMode(); | |||||
setRemoteDir(remotePath);//转移到FTP服务器目录 | |||||
UtilLogger.info("跳转到FTP服务目录:" + remotePath); | |||||
File localFile = new File(localFileName); | |||||
if (!localFile.exists()) UtilFile.CreateFile(localFileName); | |||||
FileOutputStream is = null; | |||||
try { | |||||
is = new FileOutputStream(localFile); | |||||
ftpClient.retrieveFile(gbktoiso8859(fileName), is); | |||||
} catch (IOException e) { | |||||
localFile.deleteOnExit(); | |||||
} finally { | |||||
is.close(); | |||||
} | |||||
} | |||||
/** | |||||
* 下载文件成流,使用此方法需要注意,关闭流之后要调用completePendingCommand方法 | |||||
* | |||||
* @param remotePath 远程路径 | |||||
* @param fileName 远程文件名 | |||||
* @return 文件流 | |||||
*/ | |||||
@Override | |||||
public InputStream downloadFile(String remotePath, String fileName) throws Exception { | |||||
try { | |||||
setPassiveNatWorkaroundStrategy(); | |||||
ftpClient.enterLocalPassiveMode(); | |||||
setRemoteDir(remotePath);//转移到FTP服务器目录 | |||||
return ftpClient.retrieveFileStream(gbktoiso8859(fileName)); | |||||
} catch (IOException e) { | |||||
logError("ftp下载文件失败", e); | |||||
return null; | |||||
} | |||||
} | |||||
/** | |||||
* 上传文件到ftp | |||||
* | |||||
* @param path 远程路径 | |||||
* @param filename 远程文件名 | |||||
* @param localFileName 本地文件(含路径) | |||||
* @return | |||||
*/ | |||||
@Override | |||||
public boolean uploadFile(String path, String filename, String localFileName) throws Exception { | |||||
return uploadFile(path, filename, new File(localFileName)); | |||||
} | |||||
@Override | |||||
public boolean uploadFile(String path, String filename, File localFile) throws Exception { | |||||
FileInputStream in = null; | |||||
try { | |||||
setPassiveNatWorkaroundStrategy(); | |||||
ftpClient.enterLocalPassiveMode(); | |||||
in = new FileInputStream(localFile); | |||||
setRemoteDir(path); | |||||
boolean b = ftpClient.storeFile(gbktoiso8859(filename), in); | |||||
if (!b) throw new Exception("FTP上传失败,请检查服务器配置!"); | |||||
return b; | |||||
} finally { | |||||
if (in != null) in.close(); | |||||
} | |||||
} | |||||
/** | |||||
* 删除远程文件 | |||||
* | |||||
* @param path 远程路径 | |||||
* @param filename 远程文件名 | |||||
*/ | |||||
@Override | |||||
public void deleteFile(String path, String filename) { | |||||
try { | |||||
setPassiveNatWorkaroundStrategy(); | |||||
setRemoteDir(path); | |||||
ftpClient.dele(gbktoiso8859(filename)); | |||||
} catch (IOException e) { | |||||
logError("删除文件失败", e); | |||||
} | |||||
} | |||||
@Override | |||||
public boolean existsFile(String path, String filename) { | |||||
try { | |||||
setPassiveNatWorkaroundStrategy(); | |||||
ftpClient.enterLocalPassiveMode();//设置被动模式 | |||||
setRemoteDir(path); | |||||
String[] files = ftpClient.listNames(gbktoiso8859(filename)); | |||||
return PubUtil.isNotEmpty(files); | |||||
} catch (IOException e) { | |||||
logError("判断文件是否存在失败", e); | |||||
return false; | |||||
} | |||||
} | |||||
@Override | |||||
public boolean rename(String path, String from, String to) { | |||||
try { | |||||
setPassiveNatWorkaroundStrategy(); | |||||
setRemoteDir(path); | |||||
return ftpClient.rename(gbktoiso8859(from), gbktoiso8859(to)); | |||||
} catch (IOException e) { | |||||
logError("重命名文件失败", e); | |||||
return false; | |||||
} | |||||
} | |||||
//调用返回流的方法,在处理完流后,要调用此方法。 | |||||
@Override | |||||
public boolean completePendingCommand() { | |||||
try { | |||||
setPassiveNatWorkaroundStrategy(); | |||||
return ftpClient.completePendingCommand(); | |||||
} catch (IOException e) { | |||||
UtilLogger.error("ftp关闭流出错", e); | |||||
return false; | |||||
} | |||||
} | |||||
//断开连接 | |||||
public FTPFile[] listFiles(String remotePath) throws IOException { | |||||
setPassiveNatWorkaroundStrategy(); | |||||
return ftpClient.listFiles(remotePath); | |||||
} | |||||
//断开连接 | |||||
@Override | |||||
public String[] listFileNames(String remotePath) throws Exception { | |||||
setPassiveNatWorkaroundStrategy(); | |||||
setRemoteDir("/"); | |||||
setRemoteDir(remotePath); | |||||
ftpClient.enterLocalPassiveMode();//设置被动模式 | |||||
String[] files = ftpClient.listNames(""); | |||||
List<String> list = new ArrayList<>(); | |||||
for (String s : files) { | |||||
if (!ftpClient.changeWorkingDirectory(s)) { | |||||
s = new String(s.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8); | |||||
list.add(s); | |||||
} else { | |||||
ftpClient.changeToParentDirectory(); | |||||
} | |||||
} | |||||
return list.toArray(new String[list.size()]); | |||||
} | |||||
//断开连接 | |||||
@Override | |||||
public String[] listAllFileNames(String remotePath) throws Exception { | |||||
setPassiveNatWorkaroundStrategy(); | |||||
setRemoteDir("/"); | |||||
setRemoteDir(remotePath); | |||||
ftpClient.enterLocalPassiveMode();//设置被动模式 | |||||
String[] files = ftpClient.listNames(""); | |||||
List<String> list = new ArrayList<>(); | |||||
for (String s : files) { | |||||
s = new String(s.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8); | |||||
list.add(s); | |||||
} | |||||
return list.toArray(new String[list.size()]); | |||||
} | |||||
//断开连接 | |||||
@Override | |||||
public void disconnect() { | |||||
if (isAutoFree() && ftpClient.isConnected()) { | |||||
try { | |||||
setPassiveNatWorkaroundStrategy(); | |||||
ftpClient.disconnect(); | |||||
} catch (IOException ignored) { | |||||
} | |||||
} | |||||
} | |||||
//登录 | |||||
protected boolean login(String server, int port, String user, String password) throws Exception { | |||||
for (int i = 0; i < LOGIN_REPEAT_TIMES; i++) { | |||||
ftpClient.setConnectTimeout(10000); | |||||
//if (!ftpClient.isConnected()) { | |||||
connect(server, port); | |||||
if (!ftpClient.isConnected()) continue; | |||||
//} | |||||
if (ftpClient.login(user, password)) { | |||||
ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE); | |||||
ftpClient.setDataTimeout(120000); | |||||
return true; | |||||
} | |||||
ftpClient.logout(); | |||||
Thread.sleep(100L); | |||||
} | |||||
disconnect(); | |||||
return false; | |||||
} | |||||
//连接 | |||||
private void connect(String server, int port) throws Exception { | |||||
disconnect(); | |||||
ftpClient.setDefaultPort(port); | |||||
ftpClient.connect(server); | |||||
int reply = ftpClient.getReplyCode(); | |||||
if (!FTPReply.isPositiveCompletion(reply)) { | |||||
ftpClient.disconnect(); | |||||
throw new Exception("服务器拒绝连接。"); | |||||
} | |||||
} | |||||
private void logError(String msg, Exception e) { | |||||
UtilLogger.debug(msg + " " + e.getMessage()); | |||||
} | |||||
//编码转换 | |||||
private static String gbktoiso8859(String gbk) { | |||||
try { | |||||
if (gbk == null) | |||||
return ""; | |||||
else //iso-8859-1 | |||||
return new String(gbk.getBytes("GBK"), StandardCharsets.ISO_8859_1); | |||||
} catch (Exception e) { | |||||
e.printStackTrace(); | |||||
return ""; | |||||
} | |||||
} | |||||
//编码转换 | |||||
private static String iso8859toutf8(String gbk) { | |||||
try { | |||||
if (gbk == null) | |||||
return ""; | |||||
else //iso-8859-1 | |||||
return new String(gbk.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8); | |||||
} catch (Exception e) { | |||||
e.printStackTrace(); | |||||
return ""; | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,6 @@ | |||||
package cc.smtweb.system.bpm.util.ftp; | |||||
public interface IDownloadFileWorker { | |||||
boolean isDownload(String file, String fileNamePrefix); | |||||
} |
@@ -0,0 +1,16 @@ | |||||
package cc.smtweb.system.bpm.util.ftp; | |||||
/** | |||||
* Created by AKmm at 2009-5-21 16:41:25 | |||||
* ftp服务器参数配置接口 | |||||
*/ | |||||
public interface IFtpServerConfig { | |||||
boolean isSFTP(); | |||||
String getServerIp(); | |||||
Integer getPort(); | |||||
String getUserName(); | |||||
String getPassword(); | |||||
} |
@@ -0,0 +1,59 @@ | |||||
package cc.smtweb.system.bpm.util.ftp; | |||||
import java.io.File; | |||||
import java.io.InputStream; | |||||
/** | |||||
* Created by Akmm at 2015-12-08 14:33 | |||||
*/ | |||||
public interface IFtpUtil { | |||||
//是否自动删除 | |||||
boolean isAutoFree(); | |||||
//设置自动删除 | |||||
void setAutoFree(boolean autoFree); | |||||
//登录ftp | |||||
boolean login(IFtpServerConfig ftpConf); | |||||
//退出ftp | |||||
void logout(); | |||||
//是否连接正常 | |||||
boolean isConnected(); | |||||
//设置远程目录 | |||||
boolean setRemoteDir(String path); | |||||
void mkdir(String dirName); | |||||
//删除远程路径 | |||||
void deleteFolder(String path); | |||||
void downloadFile(String remotePath, String fileName, String localPath) throws Exception; | |||||
void downloadFileEx(String remotePath, String fileName, String localFileName) throws Exception; | |||||
InputStream downloadFile(String remotePath, String fileName) throws Exception; | |||||
boolean uploadFile(String path, String filename, String localFileName) throws Exception; | |||||
boolean uploadFile(String path, String filename, File localFile) throws Exception; | |||||
void deleteFile(String path, String filename); | |||||
//判断文件是否存在 | |||||
boolean existsFile(String path, String filename); | |||||
//调用返回流的方法,在处理完流后,要调用此方法。 | |||||
boolean completePendingCommand(); | |||||
//断开连接 | |||||
// FTPFile[] listFiles(String remotePath) throws IOException; | |||||
//枚举文件名 | |||||
String[] listFileNames(String remotePath) throws Exception; | |||||
//枚举文件名,包含文件夹 | |||||
String[] listAllFileNames(String remotePath) throws Exception; | |||||
//断开连接 | |||||
void disconnect(); | |||||
boolean rename(String remotePath, String from, String to) throws Exception; | |||||
} |
@@ -0,0 +1,396 @@ | |||||
package cc.smtweb.system.bpm.util.ftp; | |||||
import cc.smtweb.framework.core.util.PubUtil; | |||||
import cc.smtweb.system.bpm.util.UtilFile; | |||||
import cc.smtweb.system.bpm.util.UtilLogger; | |||||
import com.jcraft.jsch.*; | |||||
import org.apache.commons.io.IOUtils; | |||||
import java.io.File; | |||||
import java.io.FileInputStream; | |||||
import java.io.FileOutputStream; | |||||
import java.io.InputStream; | |||||
import java.nio.charset.StandardCharsets; | |||||
import java.util.*; | |||||
/** | |||||
* 一个sftp的封装类 | |||||
*/ | |||||
@SuppressWarnings("UnusedDeclaration") | |||||
public class SFtpUtil implements IFtpUtil { | |||||
private static final int LOGIN_REPEAT_TIMES = 1; | |||||
private ChannelSftp sftp; | |||||
private boolean autoFree = true; | |||||
public SFtpUtil() { | |||||
this.sftp = null; | |||||
} | |||||
@Override | |||||
public boolean isAutoFree() { | |||||
return autoFree; | |||||
} | |||||
@Override | |||||
public void setAutoFree(boolean autoFree) { | |||||
this.autoFree = autoFree; | |||||
} | |||||
//登录ftp | |||||
@Override | |||||
public boolean login(IFtpServerConfig ftpConf) { | |||||
try { | |||||
int count = 0; | |||||
while (count < 3) { | |||||
// 设置超时时间为 5s | |||||
count++; | |||||
try { | |||||
JSch jsch = new JSch(); | |||||
jsch.getSession(ftpConf.getUserName(), ftpConf.getServerIp(), ftpConf.getPort()); | |||||
Session sshSession = jsch.getSession(ftpConf.getUserName(), ftpConf.getServerIp(), ftpConf.getPort()); | |||||
System.out.println("Session created."); | |||||
sshSession.setPassword(ftpConf.getPassword()); | |||||
Properties sshConfig = new Properties(); | |||||
sshConfig.put("StrictHostKeyChecking", "no"); | |||||
sshSession.setConfig(sshConfig); | |||||
sshSession.setTimeout(10 * 1000); | |||||
sshSession.connect(); | |||||
UtilLogger.debug("Session connected[" + count + "/3]."); | |||||
UtilLogger.debug("Opening Channel[" + count + "/3]."); | |||||
Channel channel = sshSession.openChannel("sftp"); | |||||
channel.connect(); | |||||
sftp = (ChannelSftp) channel; | |||||
UtilLogger.debug("已连接到 " + ftpConf.getServerIp() + ";"); | |||||
return true; | |||||
} catch (Exception e) { | |||||
UtilLogger.debug("connect fail[" + count + "/3]:" + PubUtil.getOrigMsg(e)); | |||||
} | |||||
} | |||||
UtilLogger.debug("sftp登录失败:3次连接超时..."); | |||||
return false; | |||||
} catch (Exception e) { | |||||
logError("sftp登录失败", e); | |||||
return false; | |||||
} | |||||
} | |||||
//退出ftp | |||||
@Override | |||||
public void logout() { | |||||
disconnect(); | |||||
} | |||||
//是否连接正常 | |||||
@Override | |||||
public boolean isConnected() { | |||||
return sftp != null && sftp.isConnected(); | |||||
/*try { | |||||
return sftpClient.sendSignal(); | |||||
} catch (IOException e) { | |||||
logError("ftp测试连接失败", e); | |||||
return false; | |||||
}*/ | |||||
} | |||||
//设置远程目录 | |||||
@Override | |||||
public boolean setRemoteDir(String path) { | |||||
String d = path; | |||||
try { | |||||
sftp.cd("/"); | |||||
sftp.cd(d); | |||||
return true; | |||||
} catch (Exception e) { | |||||
logError("sftp进远程目录失败[" + d + "],准备创建", e); | |||||
} | |||||
mkdir(d); | |||||
try { | |||||
sftp.cd(d); | |||||
return true; | |||||
} catch (Exception e) { | |||||
logError("sftp设置远程目录失败[" + d + "]", e); | |||||
return false; | |||||
} | |||||
} | |||||
private boolean openRemoteDir(String path) { | |||||
String d = path; | |||||
try { | |||||
sftp.cd(d); | |||||
return true; | |||||
} catch (Exception e) { | |||||
return false; | |||||
} | |||||
} | |||||
/** | |||||
* 创建指定文件夹 | |||||
* | |||||
* @param dirName dirName | |||||
*/ | |||||
public void mkdir(String dirName) { | |||||
String[] dirs = dirName.split("/"); | |||||
try { | |||||
String now = sftp.pwd(); | |||||
for (int i = 0; i < dirs.length; i++) { | |||||
if (PubUtil.isEmpty(dirs[i])) continue; | |||||
boolean dirExists = openRemoteDir(dirs[i]); | |||||
if (!dirExists) { | |||||
sftp.mkdir(dirs[i]); | |||||
sftp.cd(dirs[i]); | |||||
} | |||||
} | |||||
sftp.cd(now); | |||||
} catch (SftpException e) { | |||||
logError("sftp创建远程目录错误", e); | |||||
} | |||||
} | |||||
//删除远程路径 | |||||
@Override | |||||
public void deleteFolder(String path) { | |||||
try { | |||||
String d = path; | |||||
sftp.rmdir(d); | |||||
} catch (Exception e) { | |||||
logError("sftp删除远程目录失败", e); | |||||
} | |||||
} | |||||
/** | |||||
* 从ftp下载文件到本地 | |||||
* | |||||
* @param remotePath 远程路径 | |||||
* @param fileName 文件名 | |||||
* @param localPath 本地路径(不带文件名) | |||||
*/ | |||||
@Override | |||||
public void downloadFile(String remotePath, String fileName, String localPath) throws Exception { | |||||
downloadFileEx(remotePath, fileName, localPath + File.separator + fileName); | |||||
} | |||||
public boolean isFileExists(String filePath, String fileName) throws Exception { | |||||
Vector<ChannelSftp.LsEntry> vector = sftp.ls(filePath); | |||||
Iterator<ChannelSftp.LsEntry> sftpFileNames = vector.iterator(); | |||||
while (sftpFileNames.hasNext()) { | |||||
String name = sftpFileNames.next().getFilename(); | |||||
if (name.equals(fileName)) { | |||||
return true; | |||||
} | |||||
} | |||||
return false; | |||||
} | |||||
/** | |||||
* 下载文件到本地 | |||||
* | |||||
* @param remotePath 远程路径 | |||||
* @param fileName 远程文件名 | |||||
* @param localFileName 本地完全文件名(路径+文件名) | |||||
*/ | |||||
@Override | |||||
public void downloadFileEx(String remotePath, String fileName, String localFileName) throws Exception { | |||||
if (!isFileExists(remotePath, fileName)) { | |||||
throw new Exception(); | |||||
} | |||||
File file = null; | |||||
file = new File(localFileName); | |||||
if (!file.exists()) UtilFile.CreateFile(localFileName); | |||||
FileOutputStream output = null; | |||||
try { | |||||
String now = sftp.pwd(); | |||||
sftp.cd(remotePath); | |||||
UtilLogger.info("跳转到SFTP服务目录:" + remotePath); | |||||
output = new FileOutputStream(file); | |||||
sftp.get(fileName, output); | |||||
sftp.cd(now); | |||||
} catch (Exception e) { | |||||
file.deleteOnExit(); | |||||
throw e; | |||||
} finally { | |||||
IOUtils.closeQuietly(output); | |||||
} | |||||
} | |||||
/** | |||||
* 下载文件成流,使用此方法需要注意,关闭流之后要调用completePendingCommand方法 | |||||
* | |||||
* @param remotePath 远程路径 | |||||
* @param fileName 远程文件名 | |||||
* @return 文件流 | |||||
*/ | |||||
@Override | |||||
public InputStream downloadFile(String remotePath, String fileName) throws Exception { | |||||
String now = sftp.pwd(); | |||||
sftp.cd(remotePath); | |||||
//setRemoteDir(remotePath);//转移到FTP服务器目录 暂时注释 拷贝错误 | |||||
InputStream is = sftp.get(fileName); | |||||
sftp.cd(now); | |||||
return is; | |||||
} | |||||
/** | |||||
* 上传文件到ftp | |||||
* | |||||
* @param path 远程路径 | |||||
* @param filename 远程文件名 | |||||
* @param localFileName 本地文件(含路径) | |||||
* @return | |||||
*/ | |||||
@Override | |||||
public boolean uploadFile(String path, String filename, String localFileName) throws Exception { | |||||
return uploadFile(path, filename, new File(localFileName)); | |||||
} | |||||
@Override | |||||
public boolean uploadFile(String path, String filename, File localFile) throws Exception { | |||||
FileInputStream is = null; | |||||
try { | |||||
String now = sftp.pwd(); | |||||
setRemoteDir(path); | |||||
is = new FileInputStream(localFile); | |||||
try { | |||||
sftp.put(is, filename); | |||||
} finally { | |||||
IOUtils.closeQuietly(is); | |||||
} | |||||
sftp.cd(now); | |||||
if (!existsFile(path, filename)) { | |||||
throw new Exception("SFTP上传失败,请检查服务器配置!"); | |||||
} | |||||
return true; | |||||
} finally { | |||||
if (is != null) is.close(); | |||||
} | |||||
} | |||||
/** | |||||
* 删除远程文件 | |||||
* | |||||
* @param path 远程路径 | |||||
* @param filename 远程文件名 | |||||
*/ | |||||
@Override | |||||
public void deleteFile(String path, String filename) { | |||||
try { | |||||
String now = sftp.pwd(); | |||||
setRemoteDir(path); | |||||
sftp.rm(filename); | |||||
sftp.cd(now); | |||||
} catch (Exception e) { | |||||
logError("删除文件失败", e); | |||||
} | |||||
} | |||||
@Override | |||||
public boolean rename(String path, String from, String to) throws Exception { | |||||
try { | |||||
String now = sftp.pwd(); | |||||
setRemoteDir(path); | |||||
sftp.rename(from, to); | |||||
sftp.cd(now); | |||||
return true; | |||||
} catch (Exception e) { | |||||
logError("重命名文件失败", e); | |||||
return false; | |||||
} | |||||
} | |||||
//调用返回流的方法,在处理完流后,要调用此方法。 | |||||
@Override | |||||
public boolean completePendingCommand() { | |||||
return true; | |||||
} | |||||
//断开连接 | |||||
@Override | |||||
public String[] listFileNames(String remotePath) throws Exception { | |||||
List<String> list = new ArrayList<>(); | |||||
Vector<ChannelSftp.LsEntry> sftpFile = sftp.ls(remotePath); | |||||
ChannelSftp.LsEntry isEntity = null; | |||||
String fileName = null; | |||||
Iterator<ChannelSftp.LsEntry> sftpFileNames = sftpFile.iterator(); | |||||
while (sftpFileNames.hasNext()) { | |||||
isEntity = sftpFileNames.next(); | |||||
if (!isEntity.getAttrs().isDir()) { | |||||
fileName = isEntity.getFilename(); | |||||
list.add(fileName); | |||||
} | |||||
} | |||||
return list.toArray(new String[list.size()]); | |||||
} | |||||
//断开连接 | |||||
@Override | |||||
public String[] listAllFileNames(String remotePath) throws Exception { | |||||
List<String> list = new ArrayList<>(); | |||||
Vector<ChannelSftp.LsEntry> sftpFile = sftp.ls(remotePath); | |||||
ChannelSftp.LsEntry isEntity = null; | |||||
String fileName = null; | |||||
Iterator<ChannelSftp.LsEntry> sftpFileNames = sftpFile.iterator(); | |||||
while (sftpFileNames.hasNext()) { | |||||
isEntity = sftpFileNames.next(); | |||||
fileName = isEntity.getFilename(); | |||||
list.add(fileName); | |||||
} | |||||
return list.toArray(new String[list.size()]); | |||||
} | |||||
//断开连接 | |||||
@Override | |||||
public void disconnect() { | |||||
if (sftp != null && isAutoFree() && sftp.isConnected()) { | |||||
try { | |||||
if (sftp.getSession() != null) { | |||||
UtilLogger.debug("关闭连接 " + sftp.getSession().getHost() + ";"); | |||||
sftp.getSession().disconnect(); | |||||
UtilLogger.debug("Session disconnect."); | |||||
} | |||||
} catch (JSchException e) { | |||||
logError("关闭失败!", e); | |||||
} | |||||
sftp.quit(); | |||||
sftp.disconnect(); | |||||
UtilLogger.debug("Channel closed."); | |||||
sftp = null; | |||||
} | |||||
} | |||||
private void logError(String msg, Exception e) { | |||||
UtilLogger.debug(msg + ":" + e.getMessage()); | |||||
} | |||||
//编码转换 | |||||
private static String gbktoiso8859(String gbk) { | |||||
try { | |||||
if (gbk == null) | |||||
return ""; | |||||
else //iso-8859-1 | |||||
return new String(gbk.getBytes("GBK"), StandardCharsets.ISO_8859_1); | |||||
} catch (Exception e) { | |||||
e.printStackTrace(); | |||||
return ""; | |||||
} | |||||
} | |||||
@Override | |||||
public boolean existsFile(String path, String filename) { | |||||
try { | |||||
String now = sftp.pwd(); | |||||
setRemoteDir(path); | |||||
Vector<ChannelSftp.LsEntry> files = sftp.ls(filename); | |||||
sftp.cd(now); | |||||
return PubUtil.isNotEmpty(files); | |||||
} catch (SftpException e) { | |||||
logError("判断文件是否存在失败", e); | |||||
return false; | |||||
} | |||||
} | |||||
} |
@@ -62,12 +62,12 @@ public class AttachInfo extends DefaultEntity { | |||||
put("attach_path", attach_path); | put("attach_path", attach_path); | ||||
} | } | ||||
/** 附件类别 */ | /** 附件类别 */ | ||||
public int getType() { | |||||
return getInt("attach_type"); | |||||
public String getType() { | |||||
return getStr("attach_type"); | |||||
} | } | ||||
/** 附件类别 */ | /** 附件类别 */ | ||||
public void setType(int attach_type) { | |||||
public void setType(String attach_type) { | |||||
put("attach_type", attach_type); | put("attach_type", attach_type); | ||||
} | } | ||||
/** 附件大小 */ | /** 附件大小 */ | ||||
@@ -115,4 +115,14 @@ public class AttachInfo extends DefaultEntity { | |||||
public void setUserId(long attach_user_id) { | public void setUserId(long attach_user_id) { | ||||
put("attach_user_id", attach_user_id); | put("attach_user_id", attach_user_id); | ||||
} | } | ||||
/** 下载次数 */ | |||||
public int getCount() { | |||||
return getInt("attach_count"); | |||||
} | |||||
/** 下载次数 */ | |||||
public void setCount(int attach_count) { | |||||
put("attach_count", attach_count); | |||||
} | |||||
} | } |
@@ -0,0 +1,16 @@ | |||||
package cc.smtweb.system.bpm.web.sys.base.attachFolder.pojo; | |||||
import lombok.Data; | |||||
import java.io.Serializable; | |||||
@Data | |||||
public class AttachFolderPojo implements Serializable { | |||||
private static final long serialVersionUID = 1L; | |||||
private Long folderId;// | |||||
private String folderAttachPath;// | |||||
private String folderPeriod;// | |||||
private int folderMaxSeq;// | |||||
private Long folderFileCount;// | |||||
} | |||||
@@ -3,6 +3,22 @@ smtweb: | |||||
file: | file: | ||||
local-path: /data/sw/files/ | local-path: /data/sw/files/ | ||||
url: http://127.0.0.1:8888/sw/files/ | url: http://127.0.0.1:8888/sw/files/ | ||||
#访问路径,需/结尾 | |||||
attach-http-path: 'http://bjjt.jujiatech.cn/files/' | |||||
#此配置原则上可以和local-path一致,可本机路径可ftp附件路径,需/结尾 | |||||
attach-path: /jjkj/attach/ | |||||
#临时文件路径,需/结尾 | |||||
attach-temp-path: /jujia/tomcat_api/webapps/files/tempFile/ | |||||
#附件上传方式 sftp/ftp/local | |||||
attach-type: sftp | |||||
#ftp IP地址 | |||||
attach-ftp-ip: 172.26.60.191 | |||||
#ftp 端口 | |||||
attach-ftp-port: 22 | |||||
#ftp 用户名 | |||||
attach-ftp-user: gzhfile | |||||
#ftp 密码 | |||||
attach-ftp-pwd: Bjjt@2021 | |||||
bpm: | bpm: | ||||
debug: true | debug: true | ||||
# 有.idea或pom.xml文件的目录 | # 有.idea或pom.xml文件的目录 | ||||
@@ -14,6 +14,8 @@ import cc.smtweb.framework.core.exception.DbException; | |||||
import cc.smtweb.framework.core.util.DateUtil; | import cc.smtweb.framework.core.util.DateUtil; | ||||
import cc.smtweb.framework.core.util.SpringUtil; | import cc.smtweb.framework.core.util.SpringUtil; | ||||
import cc.smtweb.framework.core.util.VariableUtil; | import cc.smtweb.framework.core.util.VariableUtil; | ||||
import com.esotericsoftware.minlog.Log; | |||||
import lombok.extern.slf4j.Slf4j; | |||||
import org.apache.commons.lang3.StringUtils; | import org.apache.commons.lang3.StringUtils; | ||||
import org.springframework.util.ClassUtils; | import org.springframework.util.ClassUtils; | ||||
@@ -31,6 +33,7 @@ import java.util.Map; | |||||
* | * | ||||
* @param <T> 数据库值对象类型 | * @param <T> 数据库值对象类型 | ||||
*/ | */ | ||||
@Slf4j | |||||
public abstract class AbstractEntityDao<T> { | public abstract class AbstractEntityDao<T> { | ||||
protected ModelTable modelTable; | protected ModelTable modelTable; | ||||
protected String tableName; | protected String tableName; | ||||
@@ -62,6 +65,9 @@ public abstract class AbstractEntityDao<T> { | |||||
tableName = table.value(); | tableName = table.value(); | ||||
modelTable = ModelTableCache.getInstance().getByName(tableName); | modelTable = ModelTableCache.getInstance().getByName(tableName); | ||||
if(null == modelTable){ | |||||
log.error("未找到缓存表结构:"+tableName); | |||||
} | |||||
if (DefaultEntity.class.isAssignableFrom(type)) { | if (DefaultEntity.class.isAssignableFrom(type)) { | ||||
for (ModelField field : modelTable.getFields()) { | for (ModelField field : modelTable.getFields()) { | ||||
add(field, null, null); | add(field, null, null); | ||||
@@ -27,5 +27,6 @@ | |||||
<modules> | <modules> | ||||
<module>core</module> | <module>core</module> | ||||
<module>bpm</module> | <module>bpm</module> | ||||
<module>unit</module> | |||||
</modules> | </modules> | ||||
</project> | </project> |