感谢:Keepalived,和寄点以及网友分享的博客,以下是我整理的在
相關連接:https://blog.csdn.net/qq_39914581/article/details/88660133
https://blog.csdn.net/qq_17655941/article/details/80758133
SpringCloud feign整合FtpClient连接池实现文件上传下载微服务以及遇到的坑。
maven创建springboot
一 首先搭建zddts-ftp文件服务连接池及服务:zddts-ftp 服务提供者pom依赖的jar包,springcloud依赖的全家桶此处不说明
commons-net
commons-net
3.3
org.apache.commons
commons-pool2
2.4.2
springboot启动类:
package com.zddts;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.MultipartConfigFactory;
import org.springframework.context.annotation.Bean;
import javax.servlet.MultipartConfigElement;
@SpringBootApplication
public class ZddtsFtpApplication {
public static void main(String[] args) {
SpringApplication.run(ZddtsFtpApplication.class, args);
}
/**
* 文件上传配置
*
* @return
*/
@Bean
public MultipartConfigElement multipartConfigElement() {
MultipartConfigFactory factory = new MultipartConfigFactory();
// 单个数据大小
factory.setMaxFileSize("20480KB"); // KB,MB
/// 总上传数据大小
factory.setMaxRequestSize("61440KB");
return factory.createMultipartConfig();
}
}
yml上配置ftp相关配置路径
接下来写连接池:
FtpClient工厂类:
package com.zddts.ftp.core; import com.zddts.common.contants.ftp.FtpConstants; import org.apache.commons.net.ftp.FTP; import org.apache.commons.net.ftp.FTPClient; import org.apache.commons.net.ftp.FTPReply; import org.apache.commons.pool2.PooledObject; import org.apache.commons.pool2.PooledObjectFactory; import org.apache.commons.pool2.impl.DefaultPooledObject; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.io.IOException; /** * 连接工厂 */ @Component public class FtpClientFactory implements PooledObjectFactory
{ @Autowired FtpConfig ftpConfig; //创建连接到池中 @Override public PooledObject makeObject() { FTPClient ftpClient = new FTPClient();//创建客户端实例 return new DefaultPooledObject (ftpClient); } //销毁连接,当连接池空闲数量达到上限时,调用此方法销毁连接 @Override public void destroyObject(PooledObject pooledObject) { FTPClient ftpClient = pooledObject.getObject(); try { ftpClient.logout(); if (ftpClient.isConnected()) { ftpClient.disconnect(); } } catch (IOException e) { throw new RuntimeException("Could not disconnect from server.", e); } } //链接状态检查 @Override public boolean validateObject(PooledObject pooledObject) { FTPClient ftpClient = pooledObject.getObject(); try { return ftpClient.sendNoOp(); } catch (IOException e) { return false; } } //初始化连接 @Override public void activateObject(PooledObject pooledObject) throws Exception { FTPClient ftpClient = pooledObject.getObject(); ftpClient.connect(ftpConfig.getIp(), ftpConfig.getPort()); ftpClient.login(ftpConfig.getUserName(), ftpConfig.getPassWord()); ftpClient.setFileType(FTP.BINARY_FILE_TYPE);//设置上传文件类型为二进制,否则将无法打开文件 // 开启服务器对UTF-8的支持,如果服务器支持就用UTF-8编码,否则就使用本地编码(GBK). String LOCAL_CHARSET = "GBK"; if (FTPReply.isPositiveCompletion(ftpClient.sendCommand("OPTS UTF8", "ON"))) { LOCAL_CHARSET = "UTF-8"; } ftpClient.setControlEncoding(LOCAL_CHARSET); } //钝化连接,使链接变为可用状态 @Override public void passivateObject(PooledObject pooledObject) throws Exception { FTPClient ftpClient = pooledObject.getObject(); try { ftpClient.changeWorkingDirectory(FtpConstants.root); ftpClient.logout(); if (ftpClient.isConnected()) { ftpClient.disconnect(); } } catch (IOException e) { throw new RuntimeException("Could not disconnect from server.", e); } } // 用于连接池中获取pool属性 public FtpConfig getConfig() { return ftpConfig; } }
ftp yml配置实体类主要获取yml上ftp的相关配置(为了使用方便,我将部分配置分开定义在了常量类中FtpConstants ):
常量类FtpConstants ,当然这部分配置也可以在yml中配置:
package com.zddts.common.contants.ftp; /** * 说明:ftp配置类 * Created by luojie on 2019/04/16. */ public class FtpConstants { public static final String root = "/"; public static int MaxTotal = 20; public static final int MinIdel = 1; public static final int MaxIdle = 8; public static final int MaxWaitMillis = 3000; /** * 本地字符编码 */ public static final String LOCAL_CHARSET = "UTF-8"; // FTP协议里面,规定文件名编码为iso-8859-1 public static final String SERVER_CHARSET = "iso-8859-1"; /** * 各类文件存放规划路径目录名 */ public static final String WORKDIR_PAT = "/upload/pat";//专利文件主目录 public static final String WORKDIR_PATDATAS = "datas"; // 专利资料存放路径 public static final String WORKDIR_PATIMGS = "imgs"; // 专利图片存放路径 public static final String WORKDIR_PATCONTRACT = "contract"; // 专利合同存放路径 public static final String WORKDIR_PATPAY_ORDER_C = "payorderforc"; // 专利付款单 (对公司) public static final String WORKDIR_PATPAY_ORDER_P = "payorderforp"; // 专利付款单(对平台) public static final String WORKDIR_PAT_PROTOCOL_S = "protocols"; // 卖方专利转让协议文件 public static final String WORKDIR_PAT_PROTOCOL_B = "protocolb"; //买方专利转让协议文件 /** * 专利上传下载分类 */ public static final String TYPE_PATDATAS = "1"; // 专利资料上传下载 public static final String TYPE_PATIMGS = "2"; // 专利图片上传下载 public static final String TYPE_PATCONTRACT = "3"; // 专利合同上传下载 public static final String TYPE_PATPAY_ORDER_C = "4"; // 专利付款单 (对公司)上传下载 public static final String TYPE_PATPAY_ORDER_P = "5"; // 专利付款单(对平台)上传下载 public static final String TYPE_PAT_PROTOCOL_S = "6"; // 卖方专利转让协议文件上传下载 public static final String TYPE_PAT_PROTOCOL_B = "7"; // 买方专利转让协议文件上传下载 /**** ftp.Host=192.168.xx.xx 本机ip ftp.Port=21 ftp.UserName=root ftp.PassWord=root ftp.workDir=/images ftp.encoding=utf-8 ftp.root=/ ftp.MaxTotal=100 ftp.MinIdel=2 ftp.MaxIdle=5 ftp.MaxWaitMillis=3000 **/ }
package com.zddts.ftp.core; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; /** * 说明:ftp配置 * Created by luojie on 2019/04/16. */ @Component public class FtpConfig { @Value("${ftp.username}") private String userName; @Value("${ftp.password}") private String passWord; @Value("${ftp.host}") private String ip; @Value("${ftp.port}") private int port; public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getPassWord() { return passWord; } public void setPassWord(String passWord) { this.passWord = passWord; } public String getIp() { return ip; } public void setIp(String ip) { this.ip = ip; } public int getPort() { return port; } public void setPort(int port) { this.port = port; } }
FptPool创建:
package com.zddts.ftp.core; import com.zddts.common.contants.ftp.FtpConstants; import org.apache.commons.net.ftp.FTPClient; import org.apache.commons.pool2.impl.GenericObjectPool; import org.apache.commons.pool2.impl.GenericObjectPoolConfig; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; /** * fileName:ftpPool * description:FTP连接池 * 1.可以获取池中空闲链接 * 2.可以将链接归还到池中 * 3.当池中空闲链接不足时,可以创建链接 * author:luojie * createTime:2019-03-16 9:59 */ @Component public class FtpPool { FtpClientFactory factory; private final GenericObjectPool
internalPool; //初始化连接池 public FtpPool(@Autowired FtpClientFactory factory) { this.factory = factory; GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig(); poolConfig.setMaxTotal(FtpConstants.MaxTotal); poolConfig.setMinIdle(FtpConstants.MinIdel); poolConfig.setMaxIdle(FtpConstants.MaxIdle); poolConfig.setMaxWaitMillis(FtpConstants.MaxWaitMillis); this.internalPool = new GenericObjectPool (factory, poolConfig); } //从连接池中取连接 public FTPClient getFTPClient() { try { return internalPool.borrowObject(); } catch (Exception e) { e.printStackTrace(); return null; } } //将链接归还到连接池 public void returnFTPClient(FTPClient ftpClient) { try { internalPool.returnObject(ftpClient); } catch (Exception e) { e.printStackTrace(); } } /** * 销毁池子 */ public void destroy() { try { internalPool.close(); } catch (Exception e) { e.printStackTrace(); } } }
FtpUtil 操作类:
package com.zddts.ftp.core; import com.zddts.common.contants.ftp.FtpConstants; import com.zddts.common.utils.StringUtils; import org.apache.commons.net.ftp.FTPClient; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.io.ResourceLoader; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Component; import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletRequest; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.URLEncoder; import static com.zddts.common.contants.ftp.FtpConstants.LOCAL_CHARSET; /** * fileName:FTP工具类 * description:提供文件上传和下载 * author:luojie * createTime:2019-03-16 8:55 */ @Component public class FtpUtil { @Autowired private ResourceLoader resourceLoader; @Autowired FtpPool pool; @Autowired FtpConfig ftpConfig; /** * Description: 向FTP服务器上传文件 * * @param file 上传到FTP服务器上的文件 * @return 成功返回文件名,否则返回null * @Version2.0 */ public String[] upload(MultipartFile file, String workDirs) throws Exception { FTPClient ftpClient = pool.getFTPClient(); //开始进行文件上传 String fileName = file.getOriginalFilename(); InputStream input = file.getInputStream(); String[] ret = new String[2]; if (input.available() == 0) { ret[0] = "0"; ret[1] = "文件大小为0的文件请不要上传哦~~~"; return ret; } try { ftpClient.setControlEncoding(FtpConstants.LOCAL_CHARSET); String remote = new String(workDirs + "/" + fileName); // 设置上传目录(没有则创建) if (!createDir(workDirs, ftpClient)) { ret[0] = "0"; ret[1] = "切入FTP目录失败:" + workDirs; return ret; } // String remote = workDirs + "/" + fileName; //上传用被动模式 // ftpClient.enterRemotePassiveMode(); ftpClient.enterLocalPassiveMode(); //设置被动模式 boolean result = ftpClient.storeFile(remote, input);//执行文件传输 if (!result) {//上传失败 ret[0] = "0"; ret[1] = "上传失败文件"; return ret; } } catch (Exception e) { e.printStackTrace(); ret[0] = "0"; ret[1] = "上传失败"; return ret; } finally {//关闭资源 input.close(); System.out.println("开始归还连接"); pool.returnFTPClient(ftpClient);//归还资源 } ret[0] = "1"; ret[1] = fileName; return ret; } /** * Description: 从FTP服务器下载文件 * * @param pathName FTP服务器中的文件名 * @param request 响应客户的响应体 * @Version1.0 */ public ResponseEntitydownLoad(String pathName, HttpServletRequest request) throws IOException { FTPClient ftpClient = pool.getFTPClient(); String fileName = pathName.substring(pathName.lastIndexOf("/") + 1); HttpHeaders headers = new HttpHeaders(); ResponseEntity entity = null; InputStream in = null; ByteArrayOutputStream byteOut = null; try { // pathName = new String(pathName.getBytes(FtpConstants.LOCAL_CHARSET), // FtpConstants.SERVER_CHARSET); //下载用本地模式 ftpClient.enterLocalPassiveMode(); in = ftpClient.retrieveFileStream(pathName); //可以设置长度 在进行网络操作时往往出错,因为你调用available()方法时, // 对发发送的数据可能还没有到达,你得到的count是0。 // byte[] bytes = new byte[in.available()]; int count = 0; while (count == 0) { count = in.available(); } byte[] bytes = new byte[count]; byteOut = new ByteArrayOutputStream(); //此处大于0 不然死循环 int bufsize = 0; while ((bufsize = in.read(bytes, 0, bytes.length)) > 0) { byteOut.write(bytes, 0, bufsize); } bytes = byteOut.toByteArray(); //处理IE下载文件的中文名称乱码的问题 String header = request.getHeader("User-Agent").toUpperCase(); if (header.contains("MSIE") || header.contains("TRIDENT") || header.contains("EDGE")) { fileName = URLEncoder.encode(fileName, LOCAL_CHARSET); fileName = fileName.replace("+", "%20"); //IE下载文件名空格变+号问题 } else { //不转码 下载的文件名中文会变成 "_" fileName = new String(fileName.getBytes(), FtpConstants.SERVER_CHARSET); } headers.add("Content-Disposition", "attachment;filename=" + fileName); headers.add("filename", fileName); // headers.add("Access-Control-Expose-Headers", "Content-Disposition"); headers.add("Access-Control-Expose-Headers", "filename"); headers.setContentType(null); entity = new ResponseEntity (bytes, headers, HttpStatus.OK); } catch (Exception e) { e.printStackTrace(); } finally { // 注意要先关闭流 否则会出现卡死问题 if (in != null) { try { in.close(); } catch (IOException e) { e.printStackTrace(); } } if (byteOut != null) { try { byteOut.close(); } catch (IOException e) { e.printStackTrace(); } } System.out.println("开始归还连接"); long bgn = System.currentTimeMillis(); pool.returnFTPClient(ftpClient); long end = System.currentTimeMillis(); System.out.println("归还连接耗时:" + (end - bgn)); } return entity; } /** * Description: 从FTP服务器读取图片 * * @param fileName 需要读取的文件名 * @return 返回文件对应的Entity * @Version1.0 */ public ResponseEntity show(String fileName, String workDir) { String username = ftpConfig.getUserName(); String password = ftpConfig.getPassWord(); String host = ftpConfig.getIp(); //ftp://root:[email protected]/+fileName return ResponseEntity.ok(resourceLoader.getResource("ftp://" + username + ":" + password + "@" + host + workDir + "/" + fileName)); } /** * 创建目录(有则切换目录,没有则创建目录) * * @param dir * @return */ public boolean createDir(String dir, FTPClient ftpClient) { if (StringUtils.nullOrBlank(dir)) { return true; } String d; try { //目录编码,解决中文路径问题 d = new String(dir.toString().getBytes(LOCAL_CHARSET), "iso-8859-1"); //尝试切入目录 if (ftpClient.changeWorkingDirectory(d)) { return true; } dir = StringUtils.trimStart(dir, "/"); dir = StringUtils.trimEnd(dir, "/"); String[] arr = dir.split("/"); StringBuffer sbfDir = new StringBuffer(); //循环生成子目录 for (String s : arr) { sbfDir.append("/"); sbfDir.append(s); //目录编码,解决中文路径问题 d = new String(sbfDir.toString().getBytes("GBK"), "iso-8859-1"); //尝试切入目录 if (ftpClient.changeWorkingDirectory(d)) continue; if (!ftpClient.makeDirectory(d)) { System.out.println("[失败]ftp创建目录:" + sbfDir.toString()); return false; } System.out.println("[成功]创建ftp目录:" + sbfDir.toString()); } //将目录切换至指定路径 return ftpClient.changeWorkingDirectory(d); } catch (Exception e) { e.printStackTrace(); return false; } } }
以上整合ftp连接池完成,接下来就是Feign提供给其他服务接口FtpServerController :
package com.zddts.ftp.server.controller; import com.zddts.common.utils.R; import com.zddts.ftp.core.FtpUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletRequest; /** * 说明: * Created by luojie on 2019/04/16. */ @RestController @RequestMapping("/ftp/pturl") public class FtpServerController { //日志 private Logger log = LoggerFactory.getLogger(FtpServerController.class); @Autowired FtpUtil ftpUtil; /** * 上传 * * @param file * @param romte * @return * @throws Exception */ @PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) public R fileUpload(@RequestPart("file") MultipartFile file, @RequestParam("romte") String romte) throws Exception { //上传 String filName = ""; try { //上传 filName = ftpUtil.upload(file, romte); } catch (Exception e) { log.error("上传失败详情:" + e.getMessage()); return R.error("上传失败"); } if (!"1".equals(filName)) { return R.error("上传失败" + filName); } return R.ok("上传成功"); } /** * 下载 * * @param romte * @param request * @throws Exception */ @RequestMapping(value = "/download") public ResponseEntity
download(String romte, HttpServletRequest request) throws Exception { ResponseEntity rep = null; try { //下载 rep = ftpUtil.downLoad(romte, request); } catch (Exception e) { log.error("下载失败详情:" + e.getMessage()); } return rep; } }
至此服务提供方代码已经写好!
接下来开始写服务消费方不:
yml 配置:只要涉及到服务间文件传输的都需要配置 也可以配置在启动类中(默认好像是10mb)zuul网关的也需要设置:
http:
multipart:
max-file-size: 20Mb # Max file size,默认1M
max-request-size: 2500Mb # Max request size,默认10M
addts-patmarket:pom中的依赖
io.github.openfeign.form
feign-form
3.0.3
io.github.openfeign.form
feign-form-spring
3.0.3
feign传输设置类告知对方传输文件类型:
若不配置会报如下错误:
Could not write request: no suitable HttpMessageConverter found for request type [org.springframework.web.multipart.support.StandardMultipartHttpServletRequest$StandardMultipartFile] and content type [multipart/form-data]
package com.zddts.patmarket.client;
import feign.codec.Encoder;
import feign.form.spring.SpringFormEncoder;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.boot.web.servlet.MultipartConfigFactory;
import org.springframework.cloud.openfeign.support.SpringEncoder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.Scope;
import javax.servlet.MultipartConfigElement;
/**
* 说明:文件上传下载 feign调用需要配置该文件
* Created by luojie on 2019/04/16.
*/
@Configuration
public class MultipartSupportConfig {
@Autowired
private ObjectFactory
messageConverters;
@Bean
@Primary
@Scope("prototype")
public Encoder feignEncoder() {
return new SpringFormEncoder(new SpringEncoder(messageConverters));
}
@Bean
public feign.Logger.Level multipartLoggerLevel() {
return feign.Logger.Level.FULL;
}
/**
* 文件上传配置
*
* @return
*/
@Bean
public MultipartConfigElement multipartConfigElement() {
MultipartConfigFactory factory = new MultipartConfigFactory();
// 单个数据大小
factory.setMaxFileSize("20MB"); // KB,MB
/// 总上传数据大小
factory.setMaxRequestSize("2500MB");
return factory.createMultipartConfig();
}
}
接口类FtpServerClient api
package com.zddts.patmarket.client;
import com.zddts.common.utils.R;
import feign.codec.Encoder;
import feign.form.spring.SpringFormEncoder;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.cloud.openfeign.support.SpringEncoder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
/**
* 说明:
* Created by luojie on 2019/04/16.
*/
@FeignClient("zddts-ftp")
public interface FtpServerClient {
@PostMapping(value = "/ftp/pturl/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public R fileUpload(@RequestPart(value = "file", required = true) MultipartFile file, @RequestParam("romte") String romte) throws Exception;
@PostMapping(value = "/ftp/pturl/download")
public ResponseEntity
download(@RequestParam("romte") String romte) throws Exception;
// /**
// * 配置文件
// */
// @Configuration
// class MultipartSupportConfig {
// @Autowired
// private ObjectFactory
messageConverters; //
// @Bean
// public Encoder feignFormEncoder() {
// return new SpringFormEncoder(new SpringEncoder(messageConverters));
// }
//
//
// }
}
接下来就是真正调用的时候了:
controller:
package com.zddts.patmarket.filemage.controller;
import com.zddts.common.utils.R;
import com.zddts.patmarket.filemage.service.FileServerService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 说明:文件上传功能
* Created by luojie on 2019/04/16.
*/
@RestController
@RequestMapping("/file")
public class FileServerController {
@Autowired
private FileServerService fileServerService;
/**
* 上传文件
* 测试方法:
*
* @param file 待上传的文件
* @return 文件在服务器上的绝对路径
* @throws IOException IO异常
*/
@PostMapping("/upload")
public R fileUpload(@RequestPart("file") MultipartFile file, @RequestParam("type") String type) throws Exception {
return fileServerService.fileUpload(file, type);
}
/**
* 上传文件
* 测试方法:
*
* @param patNo 待上传的文件
* @return 文件在服务器上的绝对路径
* @throws IOException IO异常
*/
@RequestMapping(value = "/download")
@ResponseBody
public Object download(@RequestParam("patNo") String patNo, @RequestParam("consId") String consId, @RequestParam("orgNo") String orgNo, HttpServletRequest request, HttpServletResponse response) throws Exception {
ResponseEntity entity = fileServerService.download(patNo, consId, orgNo, request);
if (entity.getBody() == null) {
return R.error("文件不存在");
}
return entity;
}
}
service:
package com.zddts.patmarket.filemage.service.impl;
import com.zddts.common.contants.ftp.FtpConstants;
import com.zddts.common.utils.R;
import com.zddts.patmarket.client.FtpServerClient;
import com.zddts.patmarket.filemage.service.FileServerService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
/**
* 说明:文件上传服务
* Created by luojie on 2019/04/16.
*/
@Service
public class FileServerServiceImpl implements FileServerService {
//日志
private Logger log = LoggerFactory.getLogger(FileServerServiceImpl.class);
@Autowired
FtpServerClient ftpServerClient;
@Override
public R fileUpload(MultipartFile file, String type) throws Exception {
return ftpServerClient.fileUpload(file, FtpConstants.WORKDIR_PATDATAS);
}
@Override
public ResponseEntity
download(String patNo, String consId, String orgNo, HttpServletRequest request) throws Exception { //判断用户是否有权限
String path = "/upload/pat/datas/papatentSort测试.csv";
ResponseEntity
entity = ftpServerClient.download(path);
return entity;
}
}
启动服务测试 :
我用的是postman测试,测试完可以直接出接口文旦分享给团队成员很方便:
上传:
下载:
注意:
若ftp乱码上乱码,代码中已经处理了可能是工具有问题:
xftp设置下使用utf-8编码
以上就是springcloud 微服务ftp 基于连接池 上传的整合,需要考虑服务间超时问题,结合项目配置合理超时时间,我就不详细阐述了。
感谢www,和分享的网友。