java - 如何将FTP服务器上的文件复制到Java中同一服务器上的目录?
Posted
技术标签:
【中文标题】java - 如何将FTP服务器上的文件复制到Java中同一服务器上的目录?【英文标题】:How to copy a file on the FTP server to a directory on the same server in Java? 【发布时间】:2012-06-27 11:15:04 【问题描述】:我正在使用 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();
【问题讨论】:
你不明白什么?如果您知道源路径和远程路径,您只需打开文件进行读取(带缓冲区)并在远程路径上写入。您也可以使用操作系统特定的 api 来处理文件。 文件类型为 FTPFile。我如何在缓冲区中读写?你的意思是像FileInputStream in = new FileInputStream(file);
dreamincode.net/forums/topic/…
您是否也在if
块中尝试过f.setFileType(FTP.BINARY_FILE_TYPE);
?可能是您已经在备份目录中拥有该文件。在其他情况下,storeFile()
true 的输出是什么?还是假的?
我确实添加了f.setFileType(FTP.BINARY_FILE_TYPE);
并在每次我使用新名称放置文件时添加到备份目录中。我得到了真实的 storeFile 结果。我在最终编辑后将整个代码放在上面。
【参考方案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.
如果您使用任何其他客户端,请阅读文档,客户端实现之间不会有太大变化。
更新:
上述方法将文件移动到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
希望对你有所帮助..
【讨论】:
使用您的解决方案ftpClient.rename(from, to);
我可以重命名它,但仍保留在同一目录中,而不是我预期的目录(备份目录)。我该如何解决?我怎样才能获得备份路径?如果我想将文件复制到备份目录,第二个参数的正确路径是什么?我有根目录,所有文件都位于那里,备份目录是我在根目录下创建的。
类似ftpClient.rename("/root/your_file.txt", "/root/backup/your_file_bak.txt");
。这里要注意的一件事是它从from
目录移动到to
目录。你不会再在from
目录中拥有它了。
ohhhhhhhhh 不,我只想拥有它的副本,而不是将其移动到备份中。
好的,这有点用 ftp 客户端解决,没有直接的方法。我将使用其中一种可用方法更新我的答案..
备份 .zip 文件时,备份已损坏,但备份 .csv 文件时备份正常。应该是什么原因?【参考方案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();
【讨论】:
我应该检查服务器中是否存在文件然后进行备份然后上传文件。我想你在这里做了别的事 再正确看一遍,if(result)是文件成功存入服务器后执行的block.....【参考方案3】:要在同一服务器上备份(移动),您可以使用:
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());
【讨论】:
这不会备份/复制文件,它会移动文件。这不是这个问题的目的。【参考方案4】:没有通过 FTP 协议复制远程文件的标准方法。不过,一些 FTP 服务器支持专有或非标准扩展。
因此,如果您的服务器是带有mod_copy module 的 ProFTPD,您可以使用FTP.sendCommand
发出这两个命令:
f.sendCommand("CPFR sourcepath");
f.sendCommand("CPTO targetpath");
第二种可能性是您的服务器允许您执行任意 shell 命令。这更不常见。如果你的服务器支持这个,你可以使用SITE EXEC
命令:
SITE EXEC cp -p sourcepath targetpath
另一种解决方法是打开与 FTP 服务器的第二个连接,并通过将被动模式数据连接传送到主动模式数据连接,使服务器将文件上传到自身。这个解决方案的实现(虽然在 php 中)显示在 FTP copy a file to another place in same FTP。
如果这两种方法都不起作用,您所能做的就是将文件下载到本地临时位置,然后将其重新上传回目标位置。这就是answer by @RP- shows。
另见FTP copy a file to another place in same FTP。
【讨论】:
以上是关于java - 如何将FTP服务器上的文件复制到Java中同一服务器上的目录?的主要内容,如果未能解决你的问题,请参考以下文章