Как скопировать файл на FTP-сервер в каталог на том же сервере в Java?
Я использую Apache Commons FTP для загрузки файла. Перед загрузкой я хочу проверить, существует ли файл на сервере и сделать резервную копию из него в каталог резервного копирования на том же сервере.
Кто-нибудь знает, как скопировать файл с FTP-сервера в резервный каталог на том же сервере?
public static void uploadWithCommonsFTP(File fileToBeUpload){
FTPClient f = new FTPClient();
FTPFile backupDirectory;
try {
f.connect(server.getServer());
f.login(server.getUsername(), server.getPassword());
FTPFile[] directories = f.listDirectories();
FTPFile[] files = f.listFiles();
for(FTPFile file:directories){
if (!file.getName().equalsIgnoreCase("backup")) {
backupDirectory=file;
} else {
f.makeDirectory("backup");
}
}
for(FTPFile file: files){
if(file.getName().equals(fileToBeUpload.getName())){
//copy file to backupDirectory
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
Отредактированный код: все еще есть проблема, когда я делаю резервную копию zip файла, файл с резервным копированием поврежден.
Кто-нибудь знает причину этого?
public static void backupUploadWithCommonsFTP(File fileToBeUpload) {
FTPClient f = new FTPClient();
boolean backupDirectoryExist = false;
boolean fileToBeUploadExist = false;
FTPFile backupDirectory = null;
try {
f.connect(server.getServer());
f.login(server.getUsername(), server.getPassword());
FTPFile[] directories = f.listDirectories();
// Check for existence of backup directory
for (FTPFile file : directories) {
String filename = file.getName();
if (file.isDirectory() && filename.equalsIgnoreCase("backup")) {
backupDirectory = file;
backupDirectoryExist = true;
break;
}
}
if (!backupDirectoryExist) {
f.makeDirectory("backup");
}
// Check if file already exist on the server
f.changeWorkingDirectory("files");
FTPFile[] files = f.listFiles();
f.changeWorkingDirectory("backup");
String filePathToBeBackup="/home/user/backup/";
String prefix;
String suffix;
String fileNameToBeBackup;
FTPFile fileReadyForBackup = null;
f.setFileType(FTP.BINARY_FILE_TYPE);
f.setFileTransferMode(FTP.BINARY_FILE_TYPE);
for (FTPFile file : files) {
if (file.isFile() && file.getName().equals(fileToBeUpload.getName())) {
prefix = FilenameUtils.getBaseName(file.getName());
suffix = ".".concat(FilenameUtils.getExtension(file.getName()));
fileNameToBeBackup = prefix.concat(Calendar.getInstance().getTime().toString().concat(suffix));
filePathToBeBackup = filePathToBeBackup.concat(fileNameToBeBackup);
fileReadyForBackup = file;
fileToBeUploadExist = true;
break;
}
}
// If file already exist on the server create a backup from it otherwise just upload the file.
if(fileToBeUploadExist){
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
f.retrieveFile(fileReadyForBackup.getName(), outputStream);
InputStream is = new ByteArrayInputStream(outputStream.toByteArray());
if(f.storeUniqueFile(filePathToBeBackup, is)){
JOptionPane.showMessageDialog(null, "Backup succeeded.");
f.changeWorkingDirectory("files");
boolean reply = f.storeFile(fileToBeUpload.getName(), new FileInputStream(fileToBeUpload));
if(reply){
JOptionPane.showMessageDialog(null,"Upload succeeded.");
}else{
JOptionPane.showMessageDialog(null,"Upload failed after backup.");
}
}else{
JOptionPane.showMessageDialog(null,"Backup failed.");
}
}else{
f.changeWorkingDirectory("files");
f.setFileType(FTP.BINARY_FILE_TYPE);
f.enterLocalPassiveMode();
InputStream inputStream = new FileInputStream(fileToBeUpload);
ByteArrayInputStream in = new ByteArrayInputStream(FileUtils.readFileToByteArray(fileToBeUpload));
boolean reply = f.storeFile(fileToBeUpload.getName(), in);
System.out.println("Reply code for storing file to server: " + reply);
if(!f.completePendingCommand()) {
f.logout();
f.disconnect();
System.err.println("File transfer failed.");
System.exit(1);
}
if(reply){
JOptionPane.showMessageDialog(null,"File uploaded successfully without making backup." +
"\nReason: There wasn't any previous version of this file.");
}else{
JOptionPane.showMessageDialog(null,"Upload failed.");
}
}
//Logout and disconnect from server
in.close();
f.logout();
f.disconnect();
} catch (IOException e) {
e.printStackTrace();
}
}
Ответы
Ответ 1
Если вы используете apache commons net FTPClient
, существует прямой способ перемещения файла из одного местоположения в другое место (если user
имеет соответствующие разрешения).
ftpClient.rename(from, to);
или, если вы знакомы с ftp commands
, вы можете использовать что-то вроде
ftpClient.sendCommand(FTPCommand.yourCommand, args);
if(FTPReply.isPositiveCompletion(ftpClient.getReplyCode())) {
//command successful;
} else {
//check for reply code, and take appropriate action.
}
Если вы используете какой-либо другой клиент, просмотрите документацию, между реализацией клиента не будет больших изменений.
UPDATE:
Над подходом перемещается файл в каталог to
, т.е. файл больше не будет находиться в каталоге from
. В основном протокол ftp предназначен для передачи файлов с local <-> remote
или remote <-> other remote
, но не для переноса на сервере.
Работа вокруг здесь будет проще, получить полный файл в локальном InputStream
и записать его обратно на сервер в виде нового файла в резервном каталоге.
чтобы получить полный файл,
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ftpClient.retrieveFile(fileName, outputStream);
InputStream is = new ByteArrayInputStream(outputStream.toByteArray());
теперь сохраните этот поток в резервном каталоге. Сначала нам нужно сменить рабочий каталог на резервный каталог.
// assuming backup directory is with in current working directory
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);//binary files
ftpClient.changeWorkingDirectory("backup");
//this overwrites the existing file
ftpClient.storeFile(fileName, is);
//if you don't want to overwrite it use storeUniqueFile
Надеюсь, это поможет вам.
Ответ 2
Попробуйте этот путь,
Я использую библиотеку apache.
ftpClient.rename(from, to) упростит, я упомянул в коде ниже
где добавить ftpClient.rename(from, to).
public void goforIt(){
FTPClient con = null;
try
{
con = new FTPClient();
con.connect("www.ujudgeit.net");
if (con.login("ujud3", "Stevejobs27!!!!"))
{
con.enterLocalPassiveMode(); // important!
con.setFileType(FTP.BINARY_FILE_TYPE);
String data = "/sdcard/prerakm4a.m4a";
ByteArrayInputStream(data.getBytes());
FileInputStream in = new FileInputStream(new File(data));
boolean result = con.storeFile("/Ads/prerakm4a.m4a", in);
in.close();
if (result)
{
Log.v("upload result", "succeeded");
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ Добавить резервную копию Здесь $$$$$$$$$$$$ $$$$$$$$$$$$$$$$$$$$//
// Now here you can store the file into a backup location
// Use ftpClient.rename(from, to) to place it in backup
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ Добавить резервную копию Здесь $$$$$$$$$$$$ $$$$$$$$$$$$$$$$$$$$//
}
con.logout();
con.disconnect();
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
Ответ 3
Нет стандартного способа дублирования удаленного файла по протоколу FTP. Однако некоторые FTP-серверы поддерживают проприетарные или нестандартные расширения.
Поэтому, если вам повезло, что ваш сервер ProFTPD с модулем mod_copy, вы можете использовать FTP.sendCommand
для выпуска этих двух команд:
f.sendCommand("CPFR sourcepath");
f.sendCommand("CPTO targetpath");
Вторая возможность заключается в том, что ваш сервер позволяет выполнять произвольные команды оболочки. Это еще менее распространено. Если ваш сервер поддерживает это, вы можете использовать команду SITE EXEC
:
SITE EXEC cp -p sourcepath targetpath
Другим обходным решением является открытие второго соединения с FTP-сервером и передача сервера самому себе путем подачи данных о подключении пассивного режима к подключению данных активного режима. Реализация этого решения (в PHP хотя) показана в FTP копировать файл в другое место на одном FTP.
Если ни одно из этих действий не работает, все, что вы можете сделать, это загрузить файл в локальное временное место и повторно загрузить его обратно в целевое местоположение. Это означает, что ответ @RP- показывает.
Смотрите также FTP, скопируйте файл в другое место на том же FTP.
Ответ 4
Для резервного копирования на одном сервере (перемещение) вы можете использовать:
String source="/home/user/some";
String goal ="/home/user/someOther";
FTPFile[] filesFTP = cliente.listFiles(source);
clientFTP.changeWorkingDirectory(goal); // IMPORTANT change to final directory
for (FTPFile f : archivosFTP)
{
if(f.isFile())
{
cliente.rename(source+"/"+f.getName(), f.getName());
}
}