I would like to extend the sample ios code called SimpleURLConnections. This sample code can upload a file using HTTP POST. I have enabled my apache web server with a cgi script written in Perl to receive the HTTP POST that addresses the cgi script and successfully uploads the file. The extension I would like to make is to add a title or description of the uploaded file. I have tried to update the multipart form data in the sample code and a corresponding change to my cgi script to transfer this description, but it is failing. The cgi script cannot read in the description using the cgi.pm method called param(). I’m hoping someone can help. Here are the details:
The multipart form data BEFORE my modification looks like the following (NOTE: the SimpleURLConnections routine inserts the image file between the Content-Type and the 2nd boundary on the fly):
--Boundary-D4AFFBA9-AD92-4697-9184-7BDA128C3B97
Content-Disposition: form-data; name="fileContents"; filename="1234567/TestImage1.png"
Content-Type: image/png
--Boundary-D4AFFBA9-AD92-4697-9184-7BDA128C3B97
Content-Disposition: form-data; name="uploadButton"
Upload File
--Boundary-D4AFFBA9-AD92-4697-9184-7BDA128C3B97--
The multipart form data AFTER my modification looks like the following:
--Boundary-D4AFFBA9-AD92-4697-9184-7BDA128C3B97
Content-Disposition: form-data; name="Title"; title="Hello World"
Content-Type: text/plain
--Boundary-D4AFFBA9-AD92-4697-9184-7BDA128C3B97
Content-Disposition: form-data; name="fileContents"; filename="1234567/TestImage1.png"
Content-Type: image/png
--Boundary-D4AFFBA9-AD92-4697-9184-7BDA128C3B97
Content-Disposition: form-data; name="titleButton"
my Title
--Boundary-D4AFFBA9-AD92-4697-9184-7BDA128C3B97
Content-Disposition: form-data; name="uploadButton"
Upload File
--Boundary-D4AFFBA9-AD92-4697-9184-7BDA128C3B97--
My cgi script looks like the following:
#!/usr/bin/perl -wT
use strict;use CGI;
use CGI::Carp qw ( fatalsToBrowser );
use File::Basename;
my $upload_dir = "/Library/WebServer/Documents/upload";
my $query = new CGI;
my $title = $query->param("Title");
#if (!$title) {
# die "the title is $title. $!";
#}
if ( !$filename ) {
print $query->header ( );
die "There was a problem uploading your photo (try a smaller file). : $!";
exit;
}
...
open ( UPLOADFILE, ">$upload_dir/$filename" ) or die "$!";
while ( <$upload_filehandle> ) {
print UPLOADFILE;
}
close UPLOADFILE;
This code works fine and the uploaded file gets written to the upload_dir.
But, if I uncomment that little block of code:
if (!$title) {
die "the title is $title. $!";
}
the script dies with an error that indicates that $title has no value:
[Tue Sep 27 17:09:17 2011] [error] [client 10.0.1.2] [Tue Sep 27 17:09:17 2011] upload.cgi: Use of uninitialized value $title in print at /Library/WebServer/CGI-Executables/upload.cgi line 79.
So, is the problem with my multipart form data, the cgi script, or is it not possible to pass this data in the multipart form data? Is there an alternate way?
Thanks
Ok, after getting help from @AFresh1, I found the problem. The problem was in the details of how the multipart form data was created. First I will show the wrong way.
NSString *title = @"Hello World";
bodySuffixStr = [NSString stringWithFormat: // create the footer for the POST message
@
"\r\n"
"--%@\r\n"
"Content-Disposition: form-data; name=\"titleButton\"\r\n"
"%@\r\n\r\n"
"--%@\r\n"
"Content-Disposition: form-data; name=\"uploadButton\"\r\n"
"\r\n"
"Upload File\r\n"
"--%@--\r\n"
"\r\n",
boundaryStr,
title,
boundaryStr,
boundaryStr
];
Now the correct way (a very subtle change in the 7th line – moved the CR/LF):
NSString *title = @"Hello World";
bodySuffixStr = [NSString stringWithFormat: // create the footer for the POST message
@
"\r\n"
"--%@\r\n"
"Content-Disposition: form-data; name=\"titleButton\"\r\n"
"\r\n%@\r\n"
"--%@\r\n"
"Content-Disposition: form-data; name=\"uploadButton\"\r\n"
"\r\n"
"Upload File\r\n"
"--%@--\r\n"
"\r\n",
boundaryStr,
title,
boundaryStr,
boundaryStr
];
I believe the content goes in the space after the header
and before the next boundary not in a title attribute. The part header being everything after the boundary and before the blank line.
If you are want to get “Hello World” into $title using
$query->param('Title')I think you will need something more like this (note that Content-type defaults to text/plain):