У меня есть локальный FTP-сервер (созданный с сервером FileZilla), и есть несколько файлов XLS. Мне нужно вернуть поток ввода файла в мое приложение Java, чтобы я мог разбирать данные и т.д.
Для этого я попытался использовать FTPClient, но по какой-то причине при попытке вернуть входной поток из файлов (больше 40 КБ или) зависает FTPClient.retrieveFileStream().
Я знаю, что к этому относятся подобные вопросы, и я прочитал их все, по крайней мере, все, что мог найти, и ничего не помогло мне. Это действительно раздражает, и мне бы хотелось, если это было возможно, помочь.
Соответствующие части кода:
public FTPwrapper(){
ConfigurableApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Properties props = (Properties) context.getBean("ftp_props");
this.FTPhost = props.getProperty("host");
this.FTPuser = props.getProperty("user");
this.FTPpass = props.getProperty("pass");
this.FTPport = Integer.parseInt(props.getProperty("port"));
this.filesPath = props.getProperty("filesPath");
//start ftp connection
try {
client.connect(this.FTPhost, this.FTPport);
client.login(this.FTPuser, this.FTPpass);
client.setBufferSize(1024 * 1024);
client.enterLocalPassiveMode();
client.setFileType(FTP.BINARY_FILE_TYPE);
} catch (IOException e) {
e.printStackTrace();
}
}
public InputStream returnFileStream(String FileName){
InputStream inputstream = null;
try {
String remoteFile = this.filesPath+FileName;
inputstream = client.retrieveFileStream(remoteFile);
client.completePendingCommand();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (client.isConnected()) {
client.logout();
client.disconnect();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
return inputstream;
}
public static void main(String[] args){
FTPwrapper ftp = new FTPwrapper();
InputStream inputstream = ftp.returnFileStream("2012 m muzieju statistika.xls");
}
Журнал FPT:
...login commands...
227 Entering Passive Mode
RETR /vtipsis_data/KT/2012 m muzieju statistika.xls
50 Opening data channel for file download from server of "/vtipsis_data/KT/2012 m muzieju statistika.xls" //Hangs...
После того, как ftp-соединение, наконец, закончилось, я получаю исключение java:
java.io.IOException: Your file contains 383 sectors, but the initial DIFAT array at index 4 referenced block # 505. This isn't allowed and your file is corrupt
at org.apache.poi.poifs.storage.BlockAllocationTableReader.<init>(BlockAllocationTableReader.java:103)
at org.apache.poi.poifs.filesystem.POIFSFileSystem.<init>(POIFSFileSystem.java:151)
at org.apache.poi.hssf.usermodel.HSSFWorkbook.<init>(HSSFWorkbook.java:322)
at org.apache.poi.hssf.usermodel.HSSFWorkbook.<init>(HSSFWorkbook.java:303)
Я предполагаю, что это исключение связано с возвратом только части моего входного потока файла XLS. Так вот, моя проблема. Есть идеи, как это решить?
Это не тот ответ, который я хотел, но обходной путь, который должен быть достаточным... Вместо того, чтобы пытаться напрямую извлекать поток, используя retrieveFileStream
, я использовал retrieveFile
для загрузки файла в качестве временного системного файла и преобразовал OutputStream, который я получил от retrieveFile
для InputStream. После этого я просто удаляю загруженный временный файл.
Пробовал использовать it.sauronsoftware.ftp4j
, но у него нет метода/функции, подобного retrieveFileStream
и он может загружать только файл.
РЕДАКТИРОВАТЬ:
Я нашел способ вернуть входной поток файла без использования retrieveFileStream
или загрузки файла. Поскольку retrieveFile
возвращает OutputStream, я могу просто преобразовать OutputStream в InputStream (почему я не думал об этом раньше?), Например:
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
client.retrieveFile(remoteFile, outputStream);
InputStream inputstream = new ByteArrayInputStream(outputStream.toByteArray());