I have a script that needs to send logfiles to a web server.
NOTE: Server side uploading is already done. This is the client that needs to upload to the server.
On the server side, I have the typical cgi script that accepts any .zip file I send it under the name "file" (Example input type="file" name="file" )
So my question is: Is there an easy way to upload a .zip file to a web server via perl?
Something simple would be ideal, like:
upload_file('http://wherever.com/upload.cgi', 'somefile.zip');
You can use HTTP::Request::Common and LWP::UserAgent like this:
use strict;
use warnings;
use HTTP::Request::Common;
use LWP::UserAgent;
my $ua = LWP::UserAgent->new(
env_proxy => 1,
);
my $req = POST 'http://someserver.com/upload.cgi',
Content_Type => 'form-data',
Content => [ pageAction => 'upload', file => ['myfile.zip'] ];
$ua->request($req);
This can also be written as
use strict;
use warnings;
use LWP::UserAgent;
my $ua = LWP::UserAgent->new(
env_proxy => 1,
);
$ua->request('http://someserver.com/upload.cgi',
Content_Type => 'form-data',
Content => [ pageAction => 'upload', file => ['myfile.zip'] ]
);
This is because $ua->post(...) is the same as $ua->request(POST ...) except the special :name headers are handled first.
Related
I can connect to a remote url using the proxy from tsocks in the following way:
tsocks telnet host port
How can I do the same using the Perl's LWP::UserAgent module?
I've been so far trying it like this, but it doesn't work:
use strict;
use warnings;
use v5.16;
use LWP::UserAgent;
use HTTP::Request::Common;
use Data::Dumper;
#my $ua = LWP::UserAgent->new();
my $ua = LWP::UserAgent->new(timeout => 10,
ssl_opts => {
#verify_hostname => 0,
verify_hostname => 0,
SSL_verify_mode => '0x01',
SSL_version => 'SSLv23:!SSLv3:!SSLv2',
}
);
$ua->proxy(['http', 'https' ], 'https://proxy_host:proxy_port' );
my $request = GET ( 'https://remote_url', Accept => 'application/json' );
$request->authorization_basic( 'username', 'password' );
say $request->as_string();
my $response = $ua->request( $request );
say $response->as_string();
By the way, I don't have socks installed on this server. So I'll need to do it without them.
Thanks!
LWP::UserAgent and SOCKS
You may use LWP::Protocol::socks perl package make LWP::UserAgent SOCKS capable.
IMHO it is much better way for your own perl scripts.
tsocks may be better for legacy perl scripts you do not want to modify.
I found a solution which might be very specific for my case:
Before running the script, I just call tsocks like this:
tsocks script_name.pl
I am writing a Perl script to POST an attachment to JIRA using
REST::Client to access the API
but I am getting an error.
use REST::Client;
use warnings;
use strict;
use File::Slurp;
use MIME::Base64;
my $user = 'user';
my $pass = 'pass';
my $url = "http://******/rest/api/2/issue/BugID/attachments";
my $client = REST::Client->new();
$client->addHeader( 'Authorization', 'Basic' . encode_base64( $user . ':' . $pass ) );
$client->addHeader( 'X-Atlassian-Token', 'no-check' );
$client->setHost( $url );
# my %header = ('Authorization' => 'Basic'. encode_base64($user . ':' . $pass),'X-Atlassian-Token' => 'no-check');
my $attachment = "C:\\Folder\\Test.txt";
$client->POST(
$url,
'Content_Type' => 'form-data',
'Content' => [ 'file' => [$attachment] ]
);
if ( $client->responseCode() eq '200' ) {
print "Updated\n";
}
# print the result
print $client->responseContent() . "\n";
The error I get is
REST::Client exception: headers must be presented as a hashref at C:\Users\a\filename.pl line 24.
As shown in the code, I have tried setting headers in different ways but I still get same error.
Please suggest if there is any other method.
I have tried using JIRA module but it gives error too.
According to the documentation, the POST method:
Takes an optional body content and hashref of custom request headers.
You need to put your headers in a hashref, e.g.:
$client->POST($url, $content, {
foo => 'bar',
baz => 'qux'
});
But...it looks like you're expecting REST::Client to use HTTP::Request::Common to construct a multipart/form-data request. Unfortunately, that's not the case, so you'll have to build the content by hand.
You could use HTTP::Request::Common directly like this:
use strict;
use warnings 'all';
use 5.010;
use HTTP::Request::Common;
use REST::Client;
my $client = REST::Client->new;
my $url = 'http://www.example.com';
my $req = POST($url,
Content_Type => 'form-data',
Content => [ file => [ 'foo.txt' ] ]
);
$client->POST($url, $req->content(), {
$req->headers->flatten()
});
But this is a bit convoluted; I would recommend dropping REST::Client and using LWP::UserAgent instead. REST::Client is just a thin wrapper for LWP::UserAgent with a few convenience features, like prepending a default host to all requests. In this case, it's just getting in the way and I don't think the conveniences are worth the trouble.
From the documentation:
POST ( $url, [$body_content, %$headers] )
And you're doing:
$client->POST(
$url,
'Content_Type' => 'form-data',
'Content' => [ 'file' => [$attachment] ]
);
So - passing a list of scalars, with an arrayref at the end.
Perhaps you want something like:
$client->POST(
$url,
$attachment,
{ 'Content-Type' => 'form-data' }
);
Note the {} to construct an anonymous hash for the headers.
Although you probably want to open and include the 'attachment', because there's nothing in REST::Client about opening files and sending them automagically.
I am trying to force download a file by sending http headers via perl. the current code is as follow:
#!/usr/bin/perl
use strict;
use Session;
use CGI::Carp qw(fatalsToBrowser);
use HTTP::Headers;
HTTP::Headers->new(
Content_type => 'text/plain',
Content_disposition => 'attachment; filename=export.txt',
);
print 'just some text';
exit;
I have also included HTTP::Headers however when I run this, it prints out the text instead of downloading the content...
You're just constructing the HTTP::Headers, but it's never printed to stdout. So you have to call also the as_string method:
my $h = HTTP::Headers->new(
Content_type => 'text/plain',
Content_disposition => 'attachment; filename=export.txt',
);
print $h->as_string;
But this is just printing the HTTP header without the separator between header and body. If you want to let libwww-perl to do this for you, you can also use HTTP::Message:
use HTTP::Headers;
use HTTP::Message;
my $h = HTTP::Headers->new(
Content_type => 'text/plain',
Content_disposition => 'attachment; filename=export.txt',
);
my $content = 'just some text';
my $msg = HTTP::Message->new($h, $content);
print $msg->as_string;
To be more correct, you should probably use "\r\n" as line terminators:
print $msg->as_string("\015\012");
Another alternative is to use CGI.pm, and use the header method, which can be used to set response HTTP headers. Actually, using CGI.pm is more common than using the HTTP::* classes. The latter are more common in use when dealing with dealing with LWP::UserAgent to fetch web pages.
When you are using CGI, you can set it when printing the header via CGI that way:
my $q = CGI->new();
print $q->header(
-type => 'text/plain',
-charset => 'iso-8859-1',
-attachment => 'filename.txt',
);
ok I figured out a simpler way...
instead of using HTTP::Headers I simply printed out the following lines:
print"Content-type:text/plain\n";
print"Content-disposition:attachment; filename=export.txt\n\n";
which did the trick...
This is the code using the CGI module:
use CGI qw(:standard);
print header(-type => "text/plain", -content_disposition => "attachment; filename=filename=export.txt");
print "just some text";
I have the following code and want to attach a file using an API. This code is delivering me the URL but the file is not getting attached.
#!/usr/bin/perl
use LWP::UserAgent;
$ua = LWP::UserAgent->new;
my $response = $ua->post(Content_Type => 'application/xml');
#$ua->agent("Mozilla 8.0 blah...");
use HTTP::Request::Common qw(POST);
use LWP::UserAgent(POST);
my $request=(POST "http://Server/Test.jsp",
Content =>[
external => "false",
Filedata => "C:/Location.jpg"
]);
#$request = $ua->request($request);
my $results=$ua->request($request);
$content = $request->content;
print $content;
exit;
Well, first you have to specify the correct content-type.
my $request=(POST "http://Server/watson/api/bug/addAttachmentAPI.jsp",
Content_Type => 'form-data',
Content =>[
appGUID => "Test GUID",
Second, the file specification must be an array reference of the form [ $file, $name, ... ] where ... are optional header field/value pairs (if you don't include headers, the content-type of the file will be guessed).
Filedata => ["C:Test Location/Upload/APIs.jpg", 'APIs.jpg'],
]);
See HTTP::Request::Common for more information.
I have a Perl script trying to send a zip file like so with LWP UserAgent module
my $req = POST $url, Content_Type => 'form-data',
Content => [
submit => 1,
upfile => [ $fname ]
];
where $fname is the path of the file. On the server side though it seems my POST array only has "submit".
Should I base64 encode the file and assign it to a variable? What's the best way to do this?
Make sure the filename can be resolved. You should get an error if it cannot be, though. At least I do in my version of HTTP::Request::Common.
You don't have to encode the binary content as Base64. (Unless, of course, the server-side app happens to expect that format.)
Here's a complete sample script:
use strict;
use warnings;
use LWP::UserAgent;
use HTTP::Request::Common 'POST';
my $ua = LWP::UserAgent->new;
my $url = 'http://localhost:8888'; # Fiddler
my $req = POST $url,
Content_Type => 'form-data',
Content => [
submit => 1,
upfile => [ 'C:\temp\bla.zip' ],
];
my $line = '=' x 78 . "\n";
print $line, $req->as_string;
my $rsp = $ua->request( $req );
print $line, $rsp->as_string;