FtpAttachmentServiceImpl.java
13.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
package com.hotent.file.attachmentService;
import com.hotent.base.attachment.Attachment;
import com.hotent.base.attachment.AttachmentService;
import com.hotent.base.attachment.MultipartFileParam;
import com.hotent.base.attachment.UploadShardResult;
import com.hotent.base.exception.BaseException;
import com.hotent.base.util.AppUtil;
import com.hotent.base.util.BeanUtils;
import com.hotent.base.util.StringUtil;
import com.hotent.file.model.FtpEntity;
import com.hotent.file.model.UploadProperties;
import com.hotent.file.service.FlowUploadPropertiesService;
import com.hotent.file.util.AppFileUtil;
import org.apache.commons.net.ftp.*;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.io.*;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
@Service
public class FtpAttachmentServiceImpl implements AttachmentService{
@Resource
FlowUploadPropertiesService flowUploadPropertiesService;
//连接FTP服务器
private void connect(FtpEntity ftpEntity, FTPClient ftp){
try {
int reply;
ftp.connect(ftpEntity.getUrl(), ftpEntity.getPort());
FTPClientConfig conf = new FTPClientConfig(FTPClientConfig.SYST_NT);
conf.setServerLanguageCode("zh");
boolean loginResult = ftp.login(ftpEntity.getUsername(), ftpEntity.getPassword());
if(loginResult){
// 开启服务器对UTF-8的支持,如果服务器支持就用UTF-8编码,否则就使用本地编码(GBK).
if (FTPReply.isPositiveCompletion(ftp.sendCommand("OPTS UTF8", "ON"))) {
ftpEntity.setLOCAL_CHARSET("UTF-8");
}
ftp.setControlEncoding(ftpEntity.getLOCAL_CHARSET());
ftp.enterLocalPassiveMode(); // 设置被动模式
//设置为二进制文件,避免乱码
ftp.setFileType(FTPClient.BINARY_FILE_TYPE);
}
reply = ftp.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
ftp.disconnect();
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void upload(Attachment attachment, InputStream inputStream,String propertiesId) throws Exception {
FtpEntity ftpEntity = AppUtil.getBean(FtpEntity.class);
FTPClient ftp = new FTPClient();
//如果是流程附件,则获取其上传配置信息
ftpEntity = initUploadProperties(propertiesId,attachment,ftpEntity,true);
String path = attachment.getFilePath();
String fileName = attachment.getEntryptName()?attachment.getId():attachment.getFileName() + "." + attachment.getExtensionName();
path = replaceFileSeparator(path);
path = new String(path.getBytes(ftpEntity.getLOCAL_CHARSET()), ftpEntity.getSERVER_CHARSET());
//fileName = new String(fileName.getBytes(LOCAL_CHARSET), SERVER_CHARSET);
validConnection(ftpEntity,ftp);
// 转到指定上传目录,没有该目录则创建
CreateDirecroty(path,ftp);
ftp.setFileType(FTP.BINARY_FILE_TYPE);
boolean result = ftp.storeFile(fileName, inputStream);
if (!result) {
throw new RuntimeException("上传文件失败");
}
// 关闭输入流
inputStream.close();
}
@Override
public void download(Attachment attachment, OutputStream outStream,String propertiesId) throws Exception{
if(!this.downloadFile(attachment, outStream, propertiesId)){
throw new BaseException("要下载的文件不存在");
}
outStream.close();
}
/**
* 下载ftp文件
* @param attachment 附件信息
* @param outStream 输出流
* @param propertiesId 流程附件配置ID
* @throws Exception
*/
private Boolean downloadFile(Attachment attachment, OutputStream outStream,String propertiesId) throws Exception{
//如果是流程附件,则获取其上传配置信息
FtpEntity ftpEntity = AppUtil.getBean(FtpEntity.class);
FTPClient ftp = new FTPClient();
ftpEntity = initUploadProperties(propertiesId,attachment,ftpEntity,false);
validConnection(ftpEntity,ftp);
String path = attachment.getFilePath();
path = replaceFileSeparator(path);
String fileName = attachment.getEntryptName()?attachment.getId():attachment.getFileName() + "." + attachment.getExtensionName();
// 编码转换,避免上传到服务器上时出现中文乱码
path = getFtpPath(path);
path = new String(path.getBytes(ftpEntity.getLOCAL_CHARSET()), ftpEntity.getSERVER_CHARSET());
boolean changeResult = ftp.changeWorkingDirectory(path);// 转移到FTP服务器目录
if(!changeResult){
throw new RuntimeException("要下载的文件路径不存在");
}
FTPFile[] fs = ftp.listFiles();
boolean tag = false;
for (FTPFile ff : fs) {
String n = ff.getName();
if (n.equals(fileName)) {
tag = true;
ftp.retrieveFile(fileName, outStream);
break;
}
}
return tag;
}
@Override
public boolean chekckFile(Attachment attachment,String propertiesId) throws Exception{
//如果是流程附件,则获取其上传配置信息
FtpEntity ftpEntity =AppUtil.getBean(FtpEntity.class);
FTPClient ftp = new FTPClient();
ftpEntity = initUploadProperties(propertiesId,attachment,ftpEntity,false);
boolean ref=true;
validConnection(ftpEntity,ftp);
String path = attachment.getFilePath();
path = replaceFileSeparator(path);
String fileName = attachment.getEntryptName()?attachment.getId():attachment.getFileName() + "." + attachment.getExtensionName();
// 编码转换,避免上传到服务器上时出现中文乱码
path = getFtpPath(path);
path = new String(path.getBytes(ftpEntity.getLOCAL_CHARSET()), ftpEntity.getSERVER_CHARSET());
boolean changeResult = ftp.changeWorkingDirectory(path);// 转移到FTP服务器目录
if(!changeResult){
ref=false;
}
FTPFile[] fs = ftp.listFiles();
boolean tag = false;
for (FTPFile ff : fs) {
String n = ff.getName();
if (n.equals(fileName)) {
tag = true;
break;
}
}
if(!tag){
ref=false;
}
return ref;
}
@Override
public void remove(Attachment attachment,String propertiesId) throws Exception {
//如果是流程附件,则获取其上传配置信息
FtpEntity ftpEntity =AppUtil.getBean(FtpEntity.class);
FTPClient ftp = new FTPClient();
ftpEntity = initUploadProperties(propertiesId,attachment,ftpEntity,false);
validConnection(ftpEntity,ftp);
String path = attachment.getFilePath();
path = replaceFileSeparator(path);
String fileName = attachment.getEntryptName()?attachment.getId():attachment.getFileName()+ "." + attachment.getExtensionName();
ftp.deleteFile(path + ftpEntity.getSeparator() + fileName);
}
//验证连接
private void validConnection(FtpEntity ftpEntity,FTPClient ftp){
try{
if(!ftp.isConnected()||!ftp.isRemoteVerificationEnabled()||!ftp.sendNoOp()){
connect(ftpEntity,ftp);
}
// 重置当前目录到根目录
ftp.changeWorkingDirectory(File.separator);
}
catch(Exception e){
connect(ftpEntity,ftp);
}
}
/*//转移FTP文件目录位置(不存在的目录会自动创建)
private void changeDirectory(String path) throws Exception{
boolean changeResult = ftp.changeWorkingDirectory(path);
//转移失败,则该目录不存在
if(!changeResult){
String errorMsg = "上传文件时,创建文件路径失败";
//创建目录
int mkd = ftp.mkd(path);
if(mkd!=257){
throw new RuntimeException(errorMsg);
}
//转移到该目录
changeResult = ftp.changeWorkingDirectory(path);
if(!changeResult){
throw new RuntimeException(errorMsg);
}
}
}*/
/**
* 创建多层目录文件,如果有ftp服务器已存在该文件,则不创建,如果无,则创建
* @param remote
* @return
* @throws IOException
*/
private boolean CreateDirecroty(String remote,FTPClient ftp) throws IOException {
boolean success = true;
remote = getFtpPath(remote);
String separator = "/";
String directory = remote + separator;
// 如果远程目录不存在,则递归创建远程服务器目录
if (!directory.equalsIgnoreCase(separator) && !changeWorkingDirectory(new String(directory),ftp)) {
int start = 0;
int end = 0;
if (directory.startsWith(separator)) {
start = 1;
} else {
start = 0;
}
end = directory.indexOf(separator, start);
String path = "";
String paths = "";
while (true) {
String subDirectory = new String(remote.substring(start, end).getBytes("GBK"), "iso-8859-1");
path = path + separator + subDirectory;
if (!existFile(path,ftp)) {
if (makeDirectory(subDirectory,ftp)) {
changeWorkingDirectory(subDirectory,ftp);
} else {
System.out.println("创建目录[" + subDirectory + "]失败");
changeWorkingDirectory(subDirectory,ftp);
}
} else {
changeWorkingDirectory(subDirectory,ftp);
}
paths = paths + separator + subDirectory;
start = end + 1;
end = directory.indexOf(separator, start);
// 检查所有目录是否创建完毕
if (end <= start) {
break;
}
}
}
return success;
}
/**
* 改变目录路径
* @param directory
* @return
*/
private boolean changeWorkingDirectory(String directory,FTPClient ftp) {
boolean flag = true;
try {
flag = ftp.changeWorkingDirectory(directory);
if (flag) {
System.out.println("进入文件夹" + directory + " 成功!");
} else {
System.out.println("进入文件夹" + directory + " 失败!开始创建文件夹");
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
return flag;
}
/**
* 判断ftp服务器文件是否存在
* @param path
* @return
* @throws IOException
*/
private boolean existFile(String path,FTPClient ftp) throws IOException {
boolean flag = false;
FTPFile[] ftpFileArr = ftp.listFiles(path);
if (ftpFileArr.length > 0) {
flag = true;
}
return flag;
}
/**
* 创建目录
* @param dir
* @return
*/
private boolean makeDirectory(String dir,FTPClient ftp) {
boolean flag = true;
try {
flag = ftp.makeDirectory(dir);
if (flag) {
System.out.println("创建文件夹" + dir + " 成功!");
} else {
System.out.println("创建文件夹" + dir + " 失败!");
}
} catch (Exception e) {
e.printStackTrace();
}
return flag;
}
private String replaceFileSeparator(String path){
// 替换路径中的分隔符
String ftpFormatPath = regReplace(path, File.separator);
// 替换文件名,只保留路径
ftpFormatPath = ftpFormatPath.replaceAll("/\\w+\\.?(\\w+)?(\\s+)?$", "");
if(path.equals(ftpFormatPath)){
ftpFormatPath = getFtpPath(ftpFormatPath);
ftpFormatPath = ftpFormatPath.replaceAll("/\\w+\\.?(\\w+)?(\\s+)?$", "");
ftpFormatPath = ftpFormatPath.replaceAll("/", "\\\\");
}
return ftpFormatPath;
}
private String regReplace(String str, String replaceChar){
StringBuffer resultString = new StringBuffer();
try {
Pattern regex = Pattern.compile("[\\|/]");
Matcher regexMatcher = regex.matcher(str);
while (regexMatcher.find()) {
regexMatcher.appendReplacement(resultString, replaceChar);
}
regexMatcher.appendTail(resultString);
} catch (PatternSyntaxException ex) {
ex.printStackTrace();
}
return resultString.toString();
}
@Override
public String getStoreType() {
return "ftp";
}
/**
* 根据配置id获取文件上传配置
* @param propertiesId
* @return
*/
private FtpEntity initUploadProperties(String propertiesId,Attachment defaultFile,FtpEntity ftpEntity,boolean isUpload){
if(StringUtil.isNotEmpty(propertiesId)){
UploadProperties uploadProperties = flowUploadPropertiesService.getUploadProperties(propertiesId);
if(BeanUtils.isNotEmpty(uploadProperties)){
String location = uploadProperties.getLocation();
if(isUpload && StringUtil.isNotEmpty(location)){
location = location.replace("/", "\\");
defaultFile.setFilePath(location+defaultFile.getFilePath());
}
FtpEntity ftpEntity2 =new FtpEntity();
ftpEntity2.setUrl(uploadProperties.getFtpUrl());
ftpEntity2.setPort(uploadProperties.getFtpPort());
ftpEntity2.setUsername(uploadProperties.getFtpUserName());
ftpEntity2.setPassword(uploadProperties.getFtpPassword());
defaultFile.setEntryptName(uploadProperties.getEncryptName()== 0 ? false : true);
return ftpEntity2;
}else if(isUpload){
String sysPath = AppFileUtil.getAttachPath();
if(StringUtil.isNotEmpty(sysPath)){
sysPath = sysPath.replace("/", "\\");
defaultFile.setFilePath(sysPath+defaultFile.getFilePath());
}
}
return ftpEntity;
}
return ftpEntity;
}
@Override
public byte[] getFileBytes(Attachment attachment) throws Exception {
String propertiesId = BeanUtils.isNotEmpty(attachment)?attachment.getProp6():"";
try(ByteArrayOutputStream outStream = new ByteArrayOutputStream()){
this.downloadFile(attachment, outStream, propertiesId);
return outStream.toByteArray();
}
}
private String getFtpPath(String path){
if(StringUtil.isNotEmpty(path)){
path = path.replaceAll("\\\\", "/");
}
return path;
}
@Override
public UploadShardResult uploadByShard(MultipartFileParam multipartFileParam, Attachment attachment, String propertiesId) throws Exception {
return null;
}
@Override
public Map<String,Object> generatePolicy(Attachment attachment, String propertiesId) {
return null;
}
@Override
public String getUrl(Attachment attachment, String propertiesId) throws UnsupportedEncodingException {
return null;
}
@Override
public InputStream getFileInputStream(Attachment attachment) throws FileNotFoundException {
return null;
}
@Override
public String getFilePath(String account, String fileName) {
return AppFileUtil.getFilePath(account,fileName);
}
}