URL url = new URL("ftp://user:pass#ftp.example.com/thefolder/");
URLConnection connection = url.openConnection();
...
// List files in folder...
Using something like the above, I was wondering how I could grab a list of files within folder 'thefolder'?
Following on from this original question, I have put together this simple FTP connection which is all working and looking good. It can see all files in the /live/conf/ location and copies them all to the local /conf/ location.
The only issue is, it is copying the files but there's no content.They are all 0KB and empty.
Can anyone see anything obvious that'd be copying the filename but not file content?
try {
FTPClient ftp = new FTPClient();
ftp.connect("000.000.000.000");
ftp.login("USER", "PASSWORD");
ftp.enterLocalPassiveMode();
ftp.setFileType(FTP.BINARY_FILE_TYPE);
FTPFile[] files = ftp.listFiles("/live/conf/");
for (int i=0; i < files.length; i++) {
if (files[i].getName().contains(".csv")) {
String remoteFile1 = files[i].getName();
File downloadFile1 = new File("/var/local/import/conf/"+files[i].getName());
OutputStream outputStream1 = new BufferedOutputStream(new FileOutputStream(downloadFile1));
ftp.retrieveFile(remoteFile1, outputStream1);
outputStream1.close();
}
}
ftp.disconnect();
} catch (SocketException ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
}
The Java SE URLConnection is insuitable for the job of retrieving a list of files from a FTP host. As to FTP, it basically only supports the FTP get or put commands (retrieve or upload file). It does not support the FTP ls command (list files) which you're basically looking for, let alone many others.
You need to look for 3rd party libraries supporting the FTP ls command (and many more). A commonly used one is the Apache Commons Net FtpClient. In its javadoc is demonstrated how to issue a ls:
FTPClient f = new FTPClient();
f.connect(server);
f.login(username, password);
FTPFile[] files = f.listFiles(directory);
You could use Apache commons FTPClient
This would allow you to call listFiles with...
public static void main(String[] args) throws IOException {
FTPClient client = new FTPClient();
client.connect("c64.rulez.org");
client.enterLocalPassiveMode();
client.login("anonymous", "");
FTPFile[] files = client.listFiles("/pub");
for (FTPFile file : files) {
System.out.println(file.getName());
}
Check out this class I found. It's does the lifting for you.
Class at nsftools.com
Example would be:
FTPConnection ftpConnect = new FTPConnection();
ftpConnect.connect("ftp.example.com");
ftpConnect.login("user","pass");
System.out.println(ftpConnect.listFiles());
Related
My app stores txt files on a FTP server which are also hosted on webservice.
In the directory where I host txt files I can find other txt files. I would like to delete all files in current directory every time when I store the new ones.
Actually i was trying to use the following command:
FTPClient ftpClient = new FTPClient();
ftpClient.connect(siteFTP);
if (ftpClient.login(usrFTP, pswFTP)) {
ftpClient.enterLocalPassiveMode();
FTPFile[] remoteFiles = ftpClient.listFiles(path);
if (remoteFiles.length > 0) {
ftpClient.deleteFile("/prenotazioni/*.txt");
}
}
But even if there was txt files in that directory, FTP respose is:
> DELE /prenotazioni/*.txt
> 550 File not found
Using * won't work. After You get list of files in declared directory, You must iterate it and delete files one by one by using deleteFile(String pathname) (also checking if file name endsWith(".txt")).
Every FTPFile has method getName(). You should construct full path so FTPClient will know what file to delete. I believe it would be something like:
ftpClient.deleteFile("/prenotazioni/" + remoteFiles[i].getName());
full method:
public static void deleteFilesInFolderFtp(String dirPath, FTPClient ftpClient) {
try {
// use local passive mode to pass firewall
ftpClient.enterLocalPassiveMode();
FTPFile[] remoteFiles = ftpClient.listFiles("/" + dirPath);
if (remoteFiles.length > 0) {
for (int i = 0; i < remoteFiles.length; i++) {
ftpClient.deleteFile("/" + dirPath + "/" + remoteFiles[i].getName());
}
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
I'm using apache commons.net to access an ftp site which is the directory is in unix:
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
I'm looping thru a list with the names of the filenames I want to download on a specific ftp site
String ftpPath = "/home/user1/input/";
FileOutputStream fos = null;
File file;
try {
for (int i = 0; i < fileList.size(); i++) {
file = new File(ftpPath+fileList.get(i).toString());
OutputStream outputStream1 = new BufferedOutputStream(new FileOutputStream(file));
boolean download = ftpClient.retrieveFile("c:/test/downloadedFile.csv", outputStream1);
outputStream1.close();
if (download) {
System.out.println("File downloaded successfully !");
} else {
System.out.println("Error in downloading file ! " + downloadFile);
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
But once I try to start to download the files I get this error althougth checking the ftp site the file exists under /home/user1/input/TejasSDH_PM_AU_09_07_2014_09_00.csv -rw-r--r--:
java.io.FileNotFoundException: \home\user1\input\TejasSDH_PM_AU_09_07_2014_09_00.csv (The system cannot find the path specified)
at java.io.FileOutputStream.open(Native Method)
at java.io.FileOutputStream.<init>(FileOutputStream.java:221)
at java.io.FileOutputStream.<init>(FileOutputStream.java:110)
at com.syntronic.client.FTPDataExtract$1.downloadTejasFiles(FTPDataExtract.java:255)
at com.syntronic.client.FTPDataExtract$1.run(FTPDataExtract.java:133)
I'm thinking as the ftp site I'm connecting, the path dir is in unix home/user1/input and java is converting all the "/" to "\". Anyone has an idea on what the error in eclipse means or is something wrong with my code? thank you
You seem to be switching things around.
You are opening a file outputstream to \home\user1\input\TejasSDH_PM_AU_09_07_2014_09_00.csv and you seem to be on windows so it won't work.
You have the local path where the ftp path should go and the other way around.
Please read your errors more carefully, I'm willing to bet that line 255 in FTPDataExtract.java is:
fos = new FileOutputStream(downloadFile);
Which should alert you to the fact that it's not actually an ftp problem.
for (int i = 0; i < fileList.size(); i++) {
OutputStream output;
output = new FileOutputStream("C:/test/" + fileList.get(i).toString());
ftpClient.retrieveFile(ftpPath + fileList.get(i).toString(), output);
output.close();
}
I wrongfully switch the remote and local path, switching it properly will run the program smoothly.
i have a class in android that connect with the ftp, and store an image, that works perfect the problem is when i am trying to move the image to another directory( i use a php page to moderate that image) it doesnt have permission to handle it, i want to put the permission to 0777 but only the "java code" can do it but i dont know how,
I am using FTPClient library
this is my code
File imageFile = new File(url[0]);
FTPClient ftpClient = new FTPClient(); ftpClient.connect(InetAddress.getByName("myserver"));
ftpClient.login("login", "pass");
ftpClient.changeWorkingDirectory("directory");
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
BufferedInputStream buffIn=null;
buffIn=new BufferedInputStream(new FileInputStream(imageFile));
ftpClient.enterLocalPassiveMode();
ftpClient.storeFile(url[1]+".jpg", buffIn);
buffIn.close();
ftpClient.logout();
ftpClient.disconnect();
See the FTPClient and FTPFile API
You can do something like that :
...
ftpClient.storeFile(url[1]+".jpg", buffIn);
FTPFile file = ftpClient.mlistFile(url[1]+".jpg");
file.setPermission(FTPFile.USER_ACCESS, FTPFile.READ_PERMISSION, true);
file.setPermission(FTPFile.USER_ACCESS, FTPFile.WRITE_PERMISSION, true);
...
I made it by command
ftpClient.storeFile(url[1]+".jpg", buffIn);
boolean a = ftpClient.sendSiteCommand("chmod " + "777 " + "/absolutepath/"+url[1]+".jpg");
I want to create zip file of files which are present at one ftp location and Copy this zip file to other ftp location without saving locally.
I am able to handle this for small size of files.It works well for small size files 1 mb etc
But if file size is big like 100 MB, 200 MB , 300 MB then its giving error as,
java.io.FileNotFoundException: STOR myfile.zip : 550 The process cannot access the
file because it is being used by another process.
at sun.net.ftp.FtpClient.readReply(FtpClient.java:251)
at sun.net.ftp.FtpClient.issueCommand(FtpClient.java:208)
at sun.net.ftp.FtpClient.openDataConnection(FtpClient.java:398)
at sun.net.ftp.FtpClient.put(FtpClient.java:609)
My code is
URLConnection urlConnection=null;
ZipOutputStream zipOutputStream=null;
InputStream inputStream = null;
byte[] buf;
int ByteRead,ByteWritten=0;
***Destination where file will be zipped***
URL url = new URL("ftp://" + ftpuser+ ":" + ftppass + "#"+ ftppass + "/" +
fileNameToStore + ";type=i");
urlConnection=url.openConnection();
OutputStream outputStream = urlConnection.getOutputStream();
zipOutputStream = new ZipOutputStream(outputStream);
buf = new byte[size];
for (int i=0; i<li.size(); i++)
{
try
{
***Souce from where file will be read***
URL u= new URL((String)li.get(i)); // this li has values http://xyz.com/folder
/myPDF.pdf
URLConnection uCon = u.openConnection();
inputStream = uCon.getInputStream();
zipOutputStream.putNextEntry(new ZipEntry((String)li.get(i).substring((int)li.get(i).lastIndexOf("/")+1).trim()));
while ((ByteRead = inputStream .read(buf)) != -1)
{
zipOutputStream.write(buf, 0, ByteRead);
ByteWritten += ByteRead;
}
zipOutputStream.closeEntry();
}
catch(Exception e)
{
e.printStackTrace();
}
}
if (inputStream != null) {
try {
inputStream .close();
}
catch (Exception e) {
e.printStackTrace();
}
}
if (zipOutputStream != null) {
try {
zipOutputStream.close();
} catch (Exception e){
e.printStackTrace();
}
}
Can anybody let me know how I can avoid this error and handle large files
This is unrelated to file sizes; as the error says, you can't replace the file because some other process is currently locking it.
The reason why you see it more often with large files is because these take longer to transfer hence the chance of concurrent accesses is higher.
So the only solution is to make sure that no one uses the file when you try to transfer it. Good luck with that.
Possible other solutions:
Don't use Windows on the server.
Transfer the file under a temporary name and rename it when it's complete. That way, other processes won't see incomplete files. Always a good thing.
Use rsync instead of inventing the wheel again.
Back in the day, before we had network security, there were FTP servers that allowed 3rd party transfers. You could use site specific commands and send a file to another FTP server directly. Those days are long gone. Sigh.
Ok, maybe not long gone. Some FTP servers support the proxy command. There is a discussion here: http://www.math.iitb.ac.in/resources/manuals/Unix_Unleashed/Vol_1/ch27.htm
I'm using Apache Commons FTP to upload a file. Before uploading I want to check if the file already exists on the server and make a backup from it to a backup directory on the same server.
Does anyone know how to copy a file from a FTP server to a backup directory on the same server?
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();
}
}
Edited code: still there is a problem, when i backup zip file, the backup-ed file is corrupted.
Does any body know the reason for it?
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();
}
}
If you are using apache commons net FTPClient, there is a direct method to move a file from one location to another location (if the user has proper permissions).
ftpClient.rename(from, to);
or, If you are familiar with ftp commands, you can use something like
ftpClient.sendCommand(FTPCommand.yourCommand, args);
if(FTPReply.isPositiveCompletion(ftpClient.getReplyCode())) {
//command successful;
} else {
//check for reply code, and take appropriate action.
}
If you are using any other client, go through the documentation, There wont be much changes between client implementations.
UPDATE:
Above approach moves the file to to directory, i.e, the file won't be there in from directory anymore. Basically ftp protocol meant to be transfer the files from local <-> remote or remote <-> other remote but not to transfer with in the server.
The work around here, would be simpler, get the complete file to a local InputStream and write it back to the server as a new file in the back up directory.
to get the complete file,
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ftpClient.retrieveFile(fileName, outputStream);
InputStream is = new ByteArrayInputStream(outputStream.toByteArray());
now, store this stream to backup directory. First we need to change working directory to backup directory.
// 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
Hope this helps you..
Try this way,
I am using apache's library .
ftpClient.rename(from, to) will make it easier, i have mentioned in the code below
where to add 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");
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$Add the backup Here$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$//
// Now here you can store the file into a backup location
// Use ftpClient.rename(from, to) to place it in backup
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$Add the backup Here$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$//
}
con.logout();
con.disconnect();
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
There's no standard way to duplicate a remote file over FTP protocol. Some FTP servers support proprietary or non-standard extensions for this though.
So if your are lucky that your server is ProFTPD with mod_copy module, you can use FTP.sendCommand to issue these two commands:
f.sendCommand("CPFR sourcepath");
f.sendCommand("CPTO targetpath");
The second possibility is that your server allows you to execute arbitrary shell commands. This is even less common. If your server supports this you can use SITE EXEC command:
SITE EXEC cp -p sourcepath targetpath
Another workaround is to open a second connection to the FTP server and make the server upload the file to itself by piping a passive mode data connection to an active mode data connection. Implementation of this solution (in PHP though) is shown in FTP copy a file to another place in same FTP.
If neither of this works, all you can do is to download the file to a local temporary location and re-upload it back to the target location. This is that the answer by #RP- shows.
See also FTP copy a file to another place in same FTP.
To backup at same Server (move), can you use:
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());
}
}