in reply to Problem uploading file data using CGI

"The CGI man page suggests my $data = $query->param('POSTDATA'); If POSTed data is not of type application/x-www-form-urlencoded or multipart/form-data"

But the data you showed is of type multipart/form-data. If you're submitting a form with a file upload field, it must always be multipart/form-data.

In your last example, you are trying to open a file called /usr/local/web/users/feedback in append mode and write the data to that file. Do you have permission to modify this file? You should check the return value from open() to make sure you successfully opened the file. This is what the documentation for open says:

"When opening a file, it's usually a bad idea to continue normal execution if the request failed, so open() is frequently used in connection with die(). ... you should always check the return value from opening a file."

Here's an example of using open() with die():

open (OUTFILE,'>>','/usr/local/web/users/feedback') or die("Cannot open 'feedback' file: $!");
package Cow { use Moo; has name => (is => 'lazy', default => sub { 'Mooington' }) } say Cow->new->name

Replies are listed 'Best First'.
Re^2: Problem uploading file data using CGI
by dougconran (Novice) on Mar 17, 2013 at 20:13 UTC
    Thanks for the quick reply.

    1. The data as it comes into the web server is

    Content-Type: application/octet-stream
    and that is what is causing the problem because it really needs to be multipart/form-data. CGI.pm is supposed to be able to read application/octet-stream (and, I'm sure, does) but I'm obviously doing something wrong.

    2. I think that I've mislead you with regard to the code I'm using to try and extract the data. In both cases it was cut and pasted from the man pages because I'd changed the code in the program to many different things. Here is what I've actually used:-

    ############ First Attempt $data = $Data->param('POSTDATA'); open(FILE,">/tmp/$Filename"); print FILE $data; close(FILE); ########## Alternative attempt $handle = $Data->upload($Mtfilename); if (defined $handle) { $io_handle = $handle->handle; open(FILE,">/tmp/$Filename"); while ($bytesread = $io_handle->read($buffer,1024)) { print FILE $buffer; } close(FILE); }

      "1. The data as it comes into the web server is Content-Type: application/octet-stream"

      No, it doesn't. You're not looking at the real HTTP headers. A multipart/form-data HTTP message has an uber-header at the top, and then each form field has its own set of mini-headers.

      The Content-Type: application/octet-stream header you posted is from the file field's mini-headers. The uber-headers will say Content-Type: multipart/form-data.

      A full multipart/form-data HTTP request might look something like this:

      POST /handler.cgi HTTP/1.1 Host: http://www.example.com/ Content-Type: multipart/form-data; boundary=XYZ --XYZ Content-Disposition: form-data; name="title" Picture of Camel --XYZ Content-Disposition: form-data; name="upload" Content-Type: image/jpeg ... some binary data ... --XYZ--

      The kind of form that might result in that request is:

      <form action="http://www.example.com/handler.cgi" method="post" enctype="multipart/form-data"> <fieldset> <legend>Image upload</legend> <label>Image <input name="title"></label><br> <label>File <input name="upload" type="file"></label> <input type="submit"> </fieldset> </form>

      And my advice to check the return value of open() still stands.

      package Cow { use Moo; has name => (is => 'lazy', default => sub { 'Mooington' }) } say Cow->new->name