homepage Welcome to WebmasterWorld Guest from 174.129.130.202
register, free tools, login, search, pro membership, help, library, announcements, recent posts, open posts,
Become a Pro Member
Visit PubCon.com
Home / Forums Index / Code, Content, and Presentation / Perl Server Side CGI Scripting
Forum Library, Charter, Moderators: coopster & jatar k & phranque

Perl Server Side CGI Scripting Forum

    
Using Net:FTP to transfer remote to remote
Failing on put...
lexipixel




msg:3390109
 1:46 am on Jul 10, 2007 (gmt 0)

The following script is supposed to FTP upload ("put") a file from one server to another, (both remote).

I worked in enough HTML to display progress onscreen for testing... it is failing at the "put" command.

NOTE: the script runs on a Linux/Apache server with Perl and makes an FTP connection to an NT server, logs in, get directory info, changes directory, etc.. and works fine --- as soon as I run put it stops dead.

The file "test.txt" is in the same directory as the script... I have tried various path(s) -- and having the test file in other directories -- any clues? Guesses? Witty remarks about my stupidity? Thanks!

#!/usr/local/bin/perl
#
#
$ftp_user = 'someuser';
$ftp_pass = 'pass2345';
$ftp_remote_addr = 'ftp.example.com';
$ftp_cwd_path = '/someuser/myroot/etc';
$ftp_put_filename = 'test.txt';
#
#
use Net::FTP;
#
print "Content-type: text/html\n\n";
#
print "Connecting to: $ftp_remote_addr<br>\n<br>\n";
#
$ftp = Net::FTP->new("$ftp_remote_addr") die "Could not connect to $ftp_remote_addr : $!";
print "Connected......<br>\n<br>\n";
#
$ftp -> login("$ftp_user","$ftp_pass") die "Could not login : $!";
print "User, $ftp_user, logged in to $ftp_remote_name<br>\n<br>\n";
#
$curr_dir = $ftp -> pwd() die "Could not get PWD : $!";
print "<i>(current directory: $curr_dir)</i><br>\n<br>\n";
#
$ftp -> cwd("$ftp_cwd_path") die "Could not CWD : $!";
print "Changed Directory to $ftp_cwd_path<br>\n<br>\n";
#
$curr_dir = $ftp -> pwd() die "Could not get PWD : $!";
print "<i>(current directory: $curr_dir)</i><br>\n<br>\n";
#
$ftp -> ascii() die "Could not set ASCII mode : $!";
print "<i>(set ASCII transfer mode)</i><br>\n<br>\n";
#
$ftp -> put("$ftp_put_filename") die "Could not PUT $ftp_put_filename : $!";
#
$remote_size = $ftp -> size("$ftp_put_filename");
#
print "Remote File Size: $remote_size bytes<br>\n<br>\n";
#
$ftp -> quit;
print "Done.<br>\n<br>\n";
#
exit;
#

 

lexipixel




msg:3390188
 4:43 am on Jul 10, 2007 (gmt 0)

...talking to myself.

I got it to go a bit further and now the PUT fails with:

Could not PUT test.html : Bad file descriptor

I've tested to get the environment variables for the path, the "use Cwd;" method, etc..

I've tried all kinds of combinations of paths and syntax on the put()..

- with full path from root
- file outside cgi-bin
- file in 777 directory
- file name with no extension, ("test" in case the period was a problem)...

Questions:

in the construct:

$ftp -> put( $file1, $file2 ) die "Could not PUT $file1 as $file2 : $!<br><br>";

What should the value of "$file1" and "$file2" be?

just a file name?

a full path with file name?

special encoding, (e.g. slashes, etc?)...?

Ideas?

fabricator




msg:3390201
 5:00 am on Jul 10, 2007 (gmt 0)

try:

$ftp -> put("$ftp_put_filename") die $ftp->message;

see what you get back in return. Google turned up a few posts about people with the error "Illegal PORT command" which is a firewall problem.

lexipixel




msg:3390213
 5:24 am on Jul 10, 2007 (gmt 0)


Died at /xyz/cust/1/2/3/9999/cgi-bin/ftppub/ftppub.cgi line 49

Line 49 is the line of code with the put()...

perl_diver




msg:3390286
 7:01 am on Jul 10, 2007 (gmt 0)

Is there a file with the same name on the server you are putting the file on?

Have you tried the two argument method of put:

put(localfilename,remotefilename);

lexipixel




msg:3390319
 7:58 am on Jul 10, 2007 (gmt 0)

I thought I tried EVERY way...

put(filename.ext)
put("filename.ext")
put('filename.ext')
put(local.txt, remote.txt)
put("$file1", "$file2")
put(/path/here/local.txt, remote.txt)
put(/path/here/local.txt, /path/there/remote.txt)
etc..

in combinations with:

ascii()
binary()
pasv()

... still dies on the put() line.

I also tried stor() which does not not error out, but file is not there.

put() always fails with "No such file or directory" or "Bad File Descriptor" if I get the local or remote names/paths wrong -- but get them right and I get "Died at Line ##".

wruppert




msg:3390739
 4:24 pm on Jul 10, 2007 (gmt 0)

Only the file name should be in the put command. You have to use the cwd command to get to the correct directory first. It is like the command line ftp in that regards.

lexipixel




msg:3390877
 6:49 pm on Jul 10, 2007 (gmt 0)

Here's the latest.

If I use put() it fails.

This uses stor()

With stor() it does create the remote file -- but the file is empty, (size = 0 bytes).


#!/usr/local/bin/perl
#
$ftp_user = 'thisuser';
$ftp_pass = 'pass234';
$ftp_remote_addr = 'ftp.exaple.com';
$ftp_cwd_path = '/thisuser/wwwroot/test';
$ftp_put_filename = 'test.html';
#
use Net::FTP;
#
print "Content-type: text/html\n\n";
#
$ftp = Net::FTP->new("$ftp_remote_addr") die $ftp->message;
print "1. FTP ready<br>\n";
$ftp -> login("$ftp_user","$ftp_pass") die $ftp->message;
print "2. LOGIN $ftp_user<br>\n";
$ftp -> cwd("$ftp_cwd_path") die $ftp->message;
print "3. CWD $ftp_cwd_path<br>\n";
$ftp -> ascii() die $ftp->message;
print "4. ASCII mode<br>\n";
$ftp -> pasv () die $ftp->message;
print "5. PASV mode<br>\n";
$ftp -> stor("$ftp_put_filename") die $ftp->message;
print "6. STOR $ftp_put_filename<br>\n";
$ftp -> quit;
print "7. QUIT<br>\n";
exit;

DrDoc




msg:3390912
 7:35 pm on Jul 10, 2007 (gmt 0)

... and the file is ok too?

Have you tried a different file; perhaps one created with vi?

lexipixel




msg:3390945
 8:15 pm on Jul 10, 2007 (gmt 0)


... and the file is ok too?
Have you tried a different file; perhaps one created with vi?

-DrDoc

The file is ok... I have tried with low ASCII text only (as a .txt file), an .HTML file, (both in ASCII mode), and with .GIF files in BINARY mode... all show up in the right directory on the remote server -- but any/all have 0 byte size.

In reading the Net::FTP docs, I start thinking it may be how the remote server assigns and communicates on FTP ports.

When I use WS_FTP to transfer the file, the log is showing me port addresses like:

connecting to ###.###.###.###:48979
Connected to ###.###.###.### port 48979

Transfer a file and see:

connecting to ###.###.###.###:48986
Connected to ###.###.###.### port 48986

Here's a snip of the WS_FTP log:


connecting to ###.###.###.###:48019
Connected to ###.###.###.### port 48019
LIST
125 Data connection already open; Transfer starting.
Received 53 bytes in 0.1 secs, (5300.00 bps), transfer succeeded
226 Transfer complete.
sending myfile.jpg as myfile.jpg (1 of 1)
TYPE I
200 Type set to I.
PASV
227 Entering Passive Mode (###,###,###,###,191,83).
connecting to ###.###.###.###:48979

As I mentioned; the server I am trying to PUT (or STOR) the file to is an NT server. The machine where the script runs is *Nix.

lexipixel




msg:3391141
 1:32 am on Jul 11, 2007 (gmt 0)

Thanks for the help guys!

I got it working!

Here's what I did;

First, I changed the line that initializes the FTP session to:

$ftp = Net::FTP->new("$ftp_remote_addr", Debug => 3 ) die $ftp->message;

The verbose Debug option gave me much more detailed info about what was happening. Debug writes out what is happening with arrows, (>>>> or <<<<) at each line to tell you which way the commands and data are flowing.

It was still failing, (writing a ZERO byte file), but with the Debug in place I could see what was happening.

Since the connect was not using PORT 21 (the default), the Net::FTP docs indicated a PASSIVE connection was needed.

I was setting it using:

$ftp -> pasv();

just before the STOR command thinking that would setup the transfer as passive. I don't think it works that way, I think the entire session needs to be in passive mode, so I removed the line with the pasv() command and added "Passive=> 1" into the initialization;

$ftp = Net::FTP->new("$ftp_remote_addr", Passive => 1 ) die $ftp->message;

I then changed the stor() command back to put()

$ftp -> put("$ftp_put_filename") die $ftp->message;

Short story, now it works fine!

Here's the final script:


#!/usr/local/bin/perl
#
$ftp_user = 'thisuser';
$ftp_pass = 'pass2345';
$ftp_remote_addr = 'ftp.example.com';
$ftp_cwd_path = '/thisuser/wwwroot/test';
$ftp_put_filename = 'test.gif';
#
use Net::FTP;
#
print "Content-type: text/html\n\n";
#
$ftp = Net::FTP->new("$ftp_remote_addr", Passive => 1 ) die $ftp->message;
print "1. FTP ready<br>\n";
$ftp -> login("$ftp_user","$ftp_pass") die $ftp->message;
print "2. LOGIN $ftp_user<br>\n";
$ftp -> cwd("$ftp_cwd_path") die $ftp->message;
print "3. CWD $ftp_cwd_path<br>\n";
$ftp -> binary() die $ftp->message;
print "4. BINARY mode<br>\n";
$ftp -> put("$ftp_put_filename") die $ftp->message;
print "5. PUT $ftp_put_filename<br>\n";
$ftp -> quit;
print "6. QUIT<br>\n";
exit;

Now all I need to do is code a recursive loop and logic to set ASCII or BINARY mode on each file and I can update the NT box with content from the Linux machine.

perl_diver




msg:3391303
 7:17 am on Jul 11, 2007 (gmt 0)

very good, thanks for the update :)

Global Options:
 top home search open messages active posts  
 

Home / Forums Index / Code, Content, and Presentation / Perl Server Side CGI Scripting
rss feed

All trademarks and copyrights held by respective owners. Member comments are owned by the poster.
Home ¦ Free Tools ¦ Terms of Service ¦ Privacy Policy ¦ Report Problem ¦ About ¦ Library ¦ Newsletter
WebmasterWorld is a Developer Shed Community owned by Jim Boykin.
© Webmaster World 1996-2014 all rights reserved