回答
从SCP服务器下载文件最简单的方法是用JSch一起使用Commons VFS:
import java.io.*;
import org.apache.commons.io.FileUtils;
import org.apache.commons.vfs2.*;
public class CopyRemoteFile {
public static void copyRemoteFiles(String host, String user, String remotePath, String localPath) throws IOException {
FileSystemOptions fsOptions = new FileSystemOptions();
SftpFileSystemConfigBuilder.getInstance().setStrictHostKeyChecking(fsOptions, "no");
SftpFileSystemConfigBuilder.getInstance().setIdentities(fsOptions,
new File[] { new File(FileUtils.getUserDirectoryPath() + "/.ssh/id_dsa") });
DefaultFileSystemManager fsManager = (DefaultFileSystemManager) VFS.getManager();
String uri = "sftp://" + user + "@" + host + "/" + remotePath;
FileObject fo = fsManager.resolveFile(uri, fsOptions);
FileObject[] files = fo.getChildren();
for (FileObject file : files) {
// We will be dealing with the files here only
if (file.getType() == FileType.FILE) {
FileUtils.copyInputStreamToFile(file.getContent().getInputStream(),
new File(localPath + "/" + file.getName().getBaseName()));
}
file.close();
}
fo.close();
fsManager.close();
}
}
这只是一个例子,我在我的wiki了,所以没有什么花哨。但请记住,如果您将关闭fsManager
,则无法在同一个虚拟机中再次打开它。我在测试这个解决方案时遇到了这个问题...
尽管上面的例子没有导入任何JSch类,但是您仍然需要将它放在classpath中。
上述示例使用私钥对远程主机进行身份验证。您可以通过提供密码并修改uri来包含该密码来轻松更改该密码。
import java.io.*;
import org.apache.commons.io.*;
import org.apache.commons.vfs2.*;
import org.apache.commons.vfs2.impl.*;
import org.apache.commons.vfs2.provider.sftp.*;
public class CopyRemoteFile {
public static void copyRemoteFiles(final String host, final String user, final String remotePath, final String localPath)
throws IOException {
FileSystemOptions fsOptions = new FileSystemOptions();
SftpFileSystemConfigBuilder.getInstance().setStrictHostKeyChecking(fsOptions, "no");
SftpFileSystemConfigBuilder.getInstance().setIdentities(fsOptions,
new File[] { new File(FileUtils.getUserDirectoryPath() + "/.ssh/id_dsa") });
DefaultFileSystemManager fsManager = (DefaultFileSystemManager) VFS.getManager();
String uri = "sftp://" + user + "@" + host + "/" + remotePath;
FileObject fo = fsManager.resolveFile(uri, fsOptions);
FileObject[] files = fo.getChildren();
for (FileObject file : files) {
// We will be dealing with the files here only
File newFile = new File(localPath + "/" + file.getName().getBaseName());
if (file.getType() == FileType.FILE && newFile.lastModified() != file.getContent().getLastModifiedTime()) {
FileUtils.copyInputStreamToFile(file.getContent().getInputStream(), newFile);
newFile.setLastModified(file.getContent().getLastModifiedTime());
}
file.close();
}
fo.close();
fsManager.close();
}
}
感谢Lukasz的代码。完全正确,同步“我想从远程主机下载所有新的和修改的文件,并从本地目录上传新的和修改的文件”。下面的代码将所有文件从远程复制到本地,即使该文件未被修改。我不想下载未修改的文件。我该如何实现这个目标? – Tivakar 2012-02-15 21:49:03
请 - 请阅读API。它在那里。 'File.getContent()。getLastModifiedTime()'会给你所需要的信息。因此,比较这两者可以为您提供文件是否被修改的信息。你可以用本地文件,数据库的某个源或者存储......来检查它。只需路径,名称和最后修改时间即可。 – 2012-02-15 22:34:27
感谢卢卡斯。真的很有帮助 – Tivakar 2012-02-16 04:49:38
看:
如果需要同步文件,你可以在本地文件系统(或DB,或信息的任何其他来源)和远程文件上比较文件的日期在:http://the-project.net16.net/Projekte/projekte/Projekte/Programmieren/sftp-synchronisierung.html
有一个完整的Programm uploadet。 这里是同步部分:
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Vector;
import com.jcraft.jsch.ChannelSftp.LsEntry;
import com.jcraft.jsch.SftpException;
/*
* This is the heart of the whole Program. I hope, the descriptions are precise enought.
*/
public class Sync{
\t public String ServerPath;
\t public File LocalFolder;
\t public sFTPclient client;
\t public ArrayList<String> serverContentList;
\t public ArrayList<String> pathList;
\t \t
\t public Sync(File local, String to, sFTPclient client){
\t \t this.LocalFolder = local;
\t \t this.ServerPath = to;
\t \t this.client = client;
\t }
\t
\t /*
\t * Executed once. Sets the Server Directory if it exists.
\t * If the local folder doesn't exist on the Server, it creates it.
\t */
\t public void setServerDirectory() throws SftpException{
\t \t try{
\t \t \t client.sftpChannel.cd(ServerPath);
\t \t }catch(Exception e){
\t \t \t GUI.addToConsole(ServerPath + " don't exist on your server!");
\t \t }
\t \t
\t \t String serverFolder = ServerPath.substring(ServerPath.lastIndexOf('/')+1, ServerPath.length());
\t \t if(!LocalFolder.getName().equals(serverFolder)){
\t \t \t try{
\t \t \t \t client.sftpChannel.mkdir(LocalFolder.getName());
\t \t \t \t client.sftpChannel.cd(LocalFolder.getName());
\t \t \t } catch (Exception e){
\t \t \t \t client.sftpChannel.cd(LocalFolder.getName());
\t \t \t }
\t \t \t this.ServerPath = ServerPath + "/" + LocalFolder.getName();
\t \t \t GUI.setNewServerFolder(ServerPath);
\t \t }
\t \t serverContentList = new ArrayList<String>();
\t \t pathList = new ArrayList<String>();
\t \t
\t }
\t
\t //The contentlist contains all Filenames, that should be synchronized
\t public void setToContentList(String ServerFolder) throws SftpException{
\t \t @SuppressWarnings("unchecked")
\t \t Vector<LsEntry> fileList = client.sftpChannel.ls(ServerFolder);
\t \t int size = fileList.size();
\t \t for(int i = 0; i < size; i++){
\t \t \t if(!fileList.get(i).getFilename().startsWith(".")){
\t \t \t \t serverContentList.add(fileList.get(i).getFilename());
\t \t \t \t pathList.add(ServerFolder);
\t \t \t }
\t \t }
\t }
\t
\t /*
\t * Deletes the synchronized elements from the Lists
\t */
\t public void deleteFromLists(String name){
\t \t int \t position = serverContentList.lastIndexOf(name);
\t \t \t \t
\t \t if(position >= 0){ \t
\t \t \t serverContentList.remove(position);
\t \t \t pathList.remove(position);
\t \t }
\t }
\t
\t /*
\t * Main function for synchronizing. Works recursive for local folders.
\t */
\t @SuppressWarnings("unchecked")
\t public void synchronize(File localFolder, String ServerDir) throws SftpException, FileNotFoundException{
\t \t if(client.sftpChannel.pwd() != ServerDir){
\t \t \t client.sftpChannel.cd(ServerDir);
\t \t }
\t \t setToContentList(ServerDir);
\t \t
\t \t File[] localList = localFolder.listFiles();
\t \t Vector<LsEntry> ServerList = client.sftpChannel.ls(ServerDir);
\t \t ServerList.remove(0); ServerList.remove(0);
\t \t
\t \t /*
\t \t * Upload missing Files/Folders
\t \t */
\t \t int size = localList.length;
\t \t for(int i = 0; i < size; i++){
\t \t \t if(localList[i].isDirectory()){
\t \t \t \t if(checkFolder(localList[i], ServerDir)){
\t \t \t \t \t synchronize(localList[i], ServerDir + "/" + localList[i].getName());
\t \t \t \t \t deleteFromLists("SubFolder");
\t \t \t \t }else {
\t \t \t \t \t newFileMaster(true, localList[i], ServerDir);
\t \t \t \t }
\t \t \t } else {
\t \t \t \t checkFile(localList[i], ServerDir);
\t \t \t }
\t \t \t deleteFromLists(localList[i].getName());
\t \t }
\t }
\t
\t /*
\t * Deletes all files on the server, which are not in the local Folder. Deletes also all missing folders
\t */
\t public void deleteRest() throws SftpException, FileNotFoundException{
\t \t int size = serverContentList.size();
\t \t for(int i = 0; i < size; i++){
\t \t \t client.sftpChannel.cd(pathList.get(i));
\t \t \t newFileMaster(false, null, serverContentList.get(i));
\t \t }
\t }
\t
\t /*
\t * Copy or delete Files/Folders
\t */
\t public void newFileMaster(boolean copyOrNot, File sourcePath, String destPath) throws FileNotFoundException, SftpException{
\t \t FileMaster copy = new FileMaster(copyOrNot, sourcePath, destPath, client.sftpChannel);
\t \t copy.runMaster();
\t }
\t
\t /*
\t *Useful to find errors - Prints out the content-List every time you call the method.
\t *If you have Problems, call it before and after every changes of the serverContentList!
\t */
\t /*public void printServerContent(){
\t \t System.out.println("SERVER-Content: " + "\n");
\t \t for(int i = 0; i < serverContentList.size(); i++){
\t \t \t System.out.println(serverContentList.get(i) + " in " + pathList.get(i));
\t \t }
\t }*/
\t
\t /*
\t * Looks ond the server, if the file is there. If not, or the local file has changed, it copies the file on the server.
\t */
\t public void checkFile(File file, String path) throws SftpException, FileNotFoundException{
\t \t client.sftpChannel.cd(path);
\t \t
\t \t if(!serverContentList.contains(file.getName())){
\t \t \t newFileMaster(true, file, ServerPath);
\t \t } else {
\t \t \t Long localTimeStamp = file.lastModified();
\t \t \t Long timeStamp = client.sftpChannel.stat(file.getName()).getATime()*1000L;
\t \t \t if(localTimeStamp > timeStamp){
\t \t \t \t newFileMaster(false, null, path + "/" + file.getName());
\t \t \t \t newFileMaster(true, file, path);
\t \t \t }
\t \t }
\t \t deleteFromLists(file.getName());
\t }
\t
\t /*
\t * The same as the checkFile function. But it returns a boolean. (Easier to handle in the synchronized funtion)
\t * Don't check, if the folder has changed (I think this can't be the case)
\t */
\t public boolean checkFolder(File folder, String path) throws SftpException{
\t \t client.sftpChannel.cd(path);
\t \t if(serverContentList.contains(folder.getName())){
\t \t \t return true;
\t \t }else { return false; }
\t }
\t
}
- 1. 使用db值进行Java同步
- 2. SCP使用JSCH的二进制文件
- 3. 使用Java的SFTP文件传输JSch
- 4. 使用AsynchAppender在Java EE中进行异步记录
- 5. 在Java中使用方法进行同步?
- 6. 使用svnkit进行同步
- 7. 跨网络的文件/目录同步
- 8. 在不同的目录中使用Java的exec运行.sh文件?
- 9. 如何使用Java JSch库逐行读取远程文件?
- 10. 异口同声地同步在目录中的文件,但没有文件夹
- 11. jsch和从特定目录运行sudo
- 12. 远程进行文件系统同步
- 13. 如何使用java在OpenLdap和Active Directory之间进行同步?
- 14. 在同步内进行异步调用
- 15. 排除在嵌套目录中的特定文件使用ansible同步模块
- 16. 寻找目录同步的java库
- 17. 使用lsyncd同步多个目录
- 18. 如何使用git进行文件同步?
- 19. 仅使用ssh/scp进行文件同步
- 20. 如何使用Java SDK将目录与AWS S3同步?
- 21. 从不同目录编译java文件
- 22. 在目录中列出同一目录中的所有文件使用visual C++
- 23. 在JSch中使用channelsftp传输文件夹和子文件夹?
- 24. 用Java在独立目录中执行.exe文件
- 25. 如何在java中扫描不同目录中的文件?
- 26. 如何从Java进行同步\异步本机调用
- 27. 使用布尔值进行同步
- 28. 使用ThreadPool进行对象同步
- 29. 使用信号量进行同步
- 30. 使用pselect进行同步等待
你能更详细解释这项任务?同步programaticaly或您只是寻找一个应用程序的解决方案?同步是什么意思? – 2012-02-14 20:15:35
同步是同步。我想以编程方式做。我在我的linux机器上有一个目录,我想下载/同步目录中的文件到本地的Windows机器上。我想以编程方式执行此操作,因为我有一个名为“sync”的按钮,应该启动此过程。 – Tivakar 2012-02-14 20:43:41
对于我来说_sync_意味着我想从远程主机下载所有新的和修改的文件,并从本地目录上传新的和修改的文件。但那是我。无论如何 - 你有你的答案:) – 2012-02-14 22:06:01