Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Dear monks

want to generate a temporary file (html) on a Windows desktop and upload it to a FTP server. I am succesfull in both single operations, but I have a problem if I combine them. This is my script:

use Net::FTP; use File::Temp qw(tempfile); #Creating my html in temporary file my $temp = new File::Temp( UNLINK => 1, SUFFIX => '.html' ); open (OUT, ">$temp") || (die "Can't open $temp\n"); binmode(OUT, ":utf8"); print OUT "My file content"; close (OUT); #uploading temporary html file to server my ($ftp, $host, $user, $pass, $dir); $host = "ftp.example.com"; $user = "myusername"; $pass = "hunter2"; $dir = "interpretbank.com/UserGlossary/"; $ftp = Net::FTP->new($host, Debug => 0); $ftp->login($user, $pass) || die $ftp->message; $ftp->cwd($dir); $ftp->put($temp) || die $ftp->message; $ftp->quit; print $ftp->message; #system("start file://$temp"); #just for check, open the temporary htm +l file in local browser $temp->seek( 0, SEEK_END );

Temporary file is generated fine, but when I upload it I get the following error message: Tk::Error: Must specify remote filename with stream input at $ftp->put($temp). A couple of considerations: if I run the two parts of the script (file generation and upload) separately (but preventing the temporary file to be deleted) I can upload my file. If a use system("start file://$temp"); to test the generated file, it is displayed in the Browser without problems, which should mean the temporary file is there when I try to upload it. What am I missing?

Replies are listed 'Best First'.
Re: Generate temporary file and FTP upload
by poj (Abbot) on Jun 30, 2017 at 19:43 UTC

    see File::Temp

    $temp can be either a filehandle or filename. Try

    $ftp->put($temp->filename) || die $ftp->message;
    
    poj
      "...can be either a filehandle or filename"

      D'oh! Yes.

      Perhaps non-OO is more intuitive?

      #!/usr/bin/env perl use strict; use warnings; use File::Temp qw(tempfile); use feature qw(say); say( ( tempfile() )[1] ); __END__

      Regards, Karl

      «The Crux of the Biscuit is the Apostrophe»

      perl -MCrypt::CBC -E 'say Crypt::CBC->new(-key=>'kgb',-cipher=>"Blowfish")->decrypt_hex($ENV{KARL});'Help

      Your solution works! Thank you ! However, I am not quite sure about the difference, the reason being that if I print "$temp" (just after creating the temporary file) I get the correct filename (with path)...

Re: Generate temporary file and FTP upload
by huck (Prior) on Jun 30, 2017 at 19:49 UTC

    From http://cpansearch.perl.org/src/SHAY/libnet-3.10/lib/Net/FTP.pm

    my $localfd = ref($local) || ref(\$local) eq "GLOB"; if (!defined($remote) and 'STOU' ne uc($cmd)) { croak 'Must specify remote filename with stream input' if $localfd; ...
    While there are times $temp may seem to be a filename, it is actually an object. Im **guessing** that $ftp->put("$temp") || die $ftp->message; will fix that

Re: Generate temporary file and FTP upload
by karlgoethebier (Abbot) on Jun 30, 2017 at 19:22 UTC
    "Tk::Error...What am I missing"

    I don't know, but i wonder where TK is in your code?

    From the docs:

    "Tk::Error is invoked by perl/Tk as if by the perl code:" $mainwindow->Tk::Error("error message", location ...);

    "I'm a simple man." (B.B. King).

    Regards, Karl

    «The Crux of the Biscuit is the Apostrophe»

    perl -MCrypt::CBC -E 'say Crypt::CBC->new(-key=>'kgb',-cipher=>"Blowfish")->decrypt_hex($ENV{KARL});'Help

      That is a good point. The code is part of a bigger script with Tk. However, running it alone produces the same error (without Tk mention): "Must specify remote filename with stream input at"

        Ah, it looks like this comes from the terribly long sub _store_cmd in Net::FTP at line 782.

        «The Crux of the Biscuit is the Apostrophe»

        perl -MCrypt::CBC -E 'say Crypt::CBC->new(-key=>'kgb',-cipher=>"Blowfish")->decrypt_hex($ENV{KARL});'Help

Re: Generate temporary file and FTP upload
by thanos1983 (Parson) on Jul 01, 2017 at 16:43 UTC

    Hello Anonymous Monk,

    Although the fellow monks have provided you with knowledge, I would like to add a few comments. Do not use bare words for file handles, read here why Don't Open Files in the old way. Every time you open a file handle or close one use die or warn.

    Having said that moving on, why are you using Net::FTP when there is the secure version Net::SFTP? But if I was you I would not use any of both, I would use Net::SFTP::Foreign. Why? I am glad you ask. Simply read here Net::SFTP::Foreign Vs. Net::SFTP Vs. Net::SSH2::SFTP.

    Having said that, it comes to another question. Why you want to use File::Temp? It is great for some cases but I assume for the case that you want to use it is not exactly what you should be looking for. Here is a sample of code that is working and producing in /tmp directory the html that you want.

    I tried combining the File::Temp and the Net::SFTP::Foreign but I was getting the following error:

    Which tells me (if I am not mistaken) that I can not combine those two modules together. So any alternatives? Of course!!!!! Simply create the file add what ever html tags and document you want in send the file and simply after delete the file. So simple. How do I delete the file? Simply use unlink.

    Complete example on creating the file, sending the file through SSH (with ssh keys exchange most secure way instead of passwords etc...) and as soon as the process is complete delete the file. Voila you are done!!!! :D

    Update: I was wrong, you can combine the modules. Working example:

    Hope this helps more, BR.

    Seeking for Perl wisdom...on the process of learning...not there...yet!
      Note that File::Temp generates a file with a name unique on the local computer, but nothing guarantees that name to be also unique on the remote file system.