public String download(String ftpUrl,String sfzh){
//ftpUrl :文件夹路径 afzh:图片路径
FTPClient ftpClient = new FTPClient();
InputStream inputStream = null;
String re=null;
try {
ftpClient.connect(ftp_ip,ftp_port);//ip地址,端口号
ftpClient.login(ftp_username, ftp_password);//账户,密码
ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
//是否成功登录服务器
int reply = ftpClient.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
ftpClient.disconnect();
}
//跳转到指定目录
ftpClient.changeWorkingDirectory(ftpUrl);
//5.遍历下载的目录
FTPFile[] fs = ftpClient.listFiles();
for (FTPFile ff : fs){
//解决中文乱码问题,两次解码
byte[] bytes=ff.getName().getBytes("iso-8859-1");
String fileName=new String(bytes,"utf-8");
if(sfzh.equals(fileName)){
inputStream = ftpClient.retrieveFileStream(fileName);
}
}
if (inputStream != null) {
byte[] data=null;
ByteArrayOutputStream outStream =new ByteArrayOutputStream();
data=new byte[inputStream.available()];
int len=0;
while((len=inputStream.read(data))!=-1){
outStream.write(data,0,len);
}
data=outStream.toByteArray();
Encoder encoder=Base64.getEncoder();
re=encoder.encodeToString(data);
}
} catch (Exception e) {
e.printStackTrace();
}finally{
if(ftpClient.isConnected()){
try{
ftpClient.disconnect();
}catch(IOException e){
e.printStackTrace();
}
}
if(null != inputStream){
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return re;
}
这是网上找的代码,用是可以用的,但是我发现debug的时候一步一步走运行正常,放开断点就死循环,发现出现问题的是这两行代码
之所以出现死循环是因为 inputStream.available() 这个函数,返回的是输入流中可读取的数据大小,但是,我们从远程网络读取数据的时候是有延迟的,当我们运行到这一行的时候,会发现,远程的ftp服务器还没有把数据传过来,可读数据还是0,于是就初始化了一个空间为0的字节数组,在下面循环读取的时候,自然没办法把数据读出来。
解决的办法,初始化一个定值空间的字节数组,
byte[] data = new byte[2048];
大小视文件大小而定,个人认为需要考虑的因素有,图片大小和调用频率,毫无疑问在数组空间大小一定的情况下,图片越大,循环读取的次数越多,但是空间越大,调用频次越多产生的垃圾越多,触发gc的频次越高,对JVM也是一种负荷,个人陋见。