Login | Register For Free | Help
Search for: (Advanced)

Mailing List Archive: ModPerl: Embperl

question on multipart forms and %fdat

 

 

ModPerl embperl RSS feed   Index | Next | Previous | View Threaded


keith.watanabe at g3s

Jan 9, 2003, 12:29 AM

Post #1 of 5 (1782 views)
Permalink
question on multipart forms and %fdat

i think this issue was discussed in the past, but i really didn't see a
resolution in the mail archives so i might be covering grounds
again. still i want to work through this problem with anyone else who
encountered it and see what they did to solve it (if at all possible).

Here's the issue. Currently i have a form where i'm using the
method="post" and enctype="multipart/form-data" part of a form for
uploading an image file. when I use post in the form, my %fdat variable
produces something like (in going through my error logs):


[Mon Jan 6 22:17:49 2003] [warn] [7054]ERR: 32: Warning in Perl code: q
: name is "upload" at
/home/jadmin/projects/joshi/perl/lib/Handler/Controller.pm line 25.
[Mon Jan 6 22:17:49 2003] [warn] [7054]ERR: 32: Warning in Perl code: q
: filename is "fl.jpg"
Content-Type: image/jpeg

 ě Ó at /home/jadmin/projects/joshi/perl/lib/Handler/Controller.pm line 25.

(Note: I'm using a model-view-controller type of design pattern, so I'm
passing in %fdat and printing out warning messages in my controller module
to examine the contents)

Here, upload is supposed to be the key value and I'm assuming that the
funky looking characters are the binary file that corresponds to "upload".
filename apparently is the name of the file i'm trying to upload.

Now, if I remove the method="post" portion in the form, I don't see these
warnings, instead seeing the normal key/value pairs from the form (I have a
few more fields in my form that I'm using to store information of the file
into a database). However, by removing the "post" part, I can't get the
form to upload the image file properly, so I assume that the post part is
necessary.

Anyway, what I'm wondering is how/why having the "post" portion mangles the
variables in my form when i use embperl in a multipart type of form. I
tried this through a cgi script which wrote the file fine. When I say, do
a "use CGI" and attempt to retrieve the form values through my CGI object,
my values are still mangled in the embperl page. Also i tried hacking the
Embperl.pm module where I attempted to print the contents from the @ffld
array into my log file, but the @ffld array was of size 0.

Currently, my setup is Apache 1.3.26 on a Redhat 8.0 linux box, using
Embperl 1.3.5 and CGI.pm v 2.86, mod perl 1.26 and perl 5.8. i tried
varying the embperl version using 1.3.4 and 1.3.1, but the same results
occurred there.

thanks!

-keith


---------------------------------------------------------------------
To unsubscribe, e-mail: embperl-unsubscribe [at] perl
For additional commands, e-mail: embperl-help [at] perl


luiz at engenhosolucoes

Jan 9, 2003, 5:51 AM

Post #2 of 5 (1703 views)
Permalink
Re: question on multipart forms and %fdat [In reply to]

Em Thu, 09 Jan 2003 16:29:37 +0900
Keith Watanabe <keith.watanabe [at] g3s> escreveu:

> i think this issue was discussed in the past, but i really didn't see
> a resolution in the mail archives so i might be covering grounds
> again. still i want to work through this problem with anyone else who
> encountered it and see what they did to solve it (if at all possible).
>
> Here's the issue. Currently i have a form where i'm using the
> method="post" and enctype="multipart/form-data" part of a form for
> uploading an image file. when I use post in the form, my %fdat
> variable produces something like (in going through my error logs):
>
>
> [Mon Jan 6 22:17:49 2003] [warn] [7054]ERR: 32: Warning in Perl
> code: q : name is "upload" at
> /home/jadmin/projects/joshi/perl/lib/Handler/Controller.pm line 25.
> [Mon Jan 6 22:17:49 2003] [warn] [7054]ERR: 32: Warning in Perl
> code: q : filename is "fl.jpg"
> Content-Type: image/jpeg
>
>  ě Ó at /home/jadmin/projects/joshi/perl/lib/Handler/Controller.pm
> line 25.
>

I use file upload in Embperl without problems, can you post your form
and describe better (with code) the way you are handling %fdat to
retrieve the file?

Regards,

Luiz Fernando B. Ribeiro
Engenho Soluš§es para a Internet

---------------------------------------------------------------------
To unsubscribe, e-mail: embperl-unsubscribe [at] perl
For additional commands, e-mail: embperl-help [at] perl


keith.watanabe at g3s

Jan 9, 2003, 8:32 AM

Post #3 of 5 (1674 views)
Permalink
Re: question on multipart forms and %fdat [In reply to]

>I use file upload in Embperl without problems, can you post your form
>and describe better (with code) the way you are handling %fdat to
>retrieve the file?

oh boy. this is going to get nasty quickly. i'll try to a few code
sources without showing too much since the way i'm building my site is
kinda complex in structure. hopefully it'll be enough.

the main file containing the embperl form page is the one below. this file
mainly is used to capture the data and then send it off to the index.epl
page which contains the code for calling handler/controller object for
manipulating the %fdat and %udat variables. this page is just a view with
a few elements for displaying the results of either a lookup or after the
form is submitted for editing purposes.

<form method="POST" enctype="multipart/form-data">
<table border="0" width="100%" cellpadding="1" cellspacing="0">
<tr class="outer">
<td>
<table border="0" width="100%" cellpadding="2" cellspacing="1">
<tr class="inner">
<th colspan="2">
Add/Edit Image
</th>
</tr>
[$ if $fdat{msg}->{msg} $]
<tr class="error">
<td align="center" colspan="2">
[+ $fdat{msg}->{msg} +]
</td>
</tr>
[$ endif $]
[$ if defined $fdat{msg}->{data}->{image}->{id} $]
<tr class="inner">
<td colspan="2" align="center">
<img src="[+ $fdat{msg}->{data}->{image}->{url} +]"
width="[+ $fdat{msg}->{data}->{image}->{width} +]"
height="[+ $fdat{msg}->{data}->{image}->{height} +]">
</td>
</tr>
[$ endif $]
<tr class="inner">
<td width="50%" align="right">
Load Image:
</td>
<td width="50%" align="left">
<input type="file" name="upload">
</td>
</tr>
<tr class="inner">
<td align="right">
Image Type:
</td>
<td>
[-
$fdat{image_type_id} =
$fdat{msg}->{data}->{image}->{image_type_id}
if
$fdat{msg}->{data}->{image}->{image_type_id};
Execute('image_type_select.epl');
-]
</td>
</tr>
<tr class="inner">
<td width="50%" align="right">
Height:
</td>
<td width="50%" align="left">
<input type="text" name="height" value="[+
$fdat{msg}->{data}->{image}->{height} +]">
</td>
</tr>
<tr class="inner">
<td align="right">
Width:
</td>
<td>
<input type="text" name="width" value="[+
$fdat{msg}->{data}->{image}->{width} +]">
</td>
</tr>
<tr class="inner">
<td colspan="2" align="center">
<input type="submit" name="act::insert" value="Add"
onClick="return checkAdd()">
[$ if defined $fdat{msg}->{data}->{image}->{id} $]
<input type="submit" name="act::update"
value="Update" onClick="return checkEdit()">
[$ endif $]
</td>
</tr>
</table>
</td>
</tr>
</table>
<input type="hidden" name="id" value="[+ $fdat{msg}->{data}->{image}->{id} +]">
<input type="hidden" name="e" value="add_image">
</form>

this next page is the controller kind of view which makes calls to
instantiate a controller object and hand the request and session
information to the controller object (as well as some customized
environment settings which is represented by the
$Apache::system->{config} and $Apache::ep references).


[.-

use Handler::Controller;

my $controller = new Handler::Controller(
system => $Apache::system->{config},
event => $Apache::ep,
session => \%udat,
request => \%fdat
);
$fdat{msg} = $controller->process();
if (defined $fdat{msg}->{data}->{dude})
{
$udat{user} = $fdat{msg}->{data};
}
-]
<html>
<head>
</head>
<body>
[- Execute ('header.epl') -]
<p>
[- Execute ($fdat{msg}->{page}) -]
</p>
</body>
</html>

the next object is handles the request data and assembles it into hash refs
(or occasionally array refs depending on the application). I do this to
segregate my data so that I can send it to an appropriate data object for
persisting in my database. However, you'll note here that there is a piece
of code that says:

upload => $q->{upload} which represents the uploaded file.

package Builder::AddImage;

use Builder::Base;
use strict;

@Builder::AddImage::ISA = qw(Builder::Base);

sub init
{
my ($self, $class, %args) = @_;
$self->{image} = {};
}

sub build
{
my $self = shift;
my $q = $self->{request};
$self->{image} = {
id => $q->{id} || 0,
image_type_id => $q->{select_image_type},
height => $q->{height},
width => $q->{width},
upload => $q->{upload},
};
return 1;
}

1;

the file that writes the file to my server is the one below. i think it's
pretty close to how a lot upload scripts handle saving a file to the
server, except that i use an object to handle it.

package Utilities::Upload;

use strict;

sub new
{
my ($class, %args) = @_;
my $self = {};
$self->{file} ||= $args{file};
$self->{dest} ||= $args{dest};
bless $self, ref $class || $class;
}

sub upload
{
my $self = shift;
my $file = "$self->{dest}/$self->{file}";
unlink $file if -e $file;
open FILE, ">>$file" || die $!;
my $buffer;
my $totallength = 0;
my $bytes;
while( $bytes = read($self->{file}, $buffer, 1024) )
{
print FILE $buffer;
$totallength += $bytes;
}
close FILE;
close $self->{file};
}

1;

anyway, there's a few pieces i'm leaving out like the controller object
itself, the system configuration and event processors, and the business
logic modules (this is just for the sake of brevity). in this case though,
i don't think they're necessary to show because the %fdat variable doesn't
really make it to the objects at those levels. however, i did notice
something about what happens when you do a post and multiform together. it
seems that there are two keys that result in the %fdat hash which are "
name" (note the space) and " filename" which contains the filename and the
contents of the file. In the " name" key, you'll see the remaining
key/value pairs. i'm curious why this occurs in this situation. are you
supposed to parse the %fdat in a "special" manner when handling file
uploads? what if you, for instance, you have multiple input fields that
you want to submit? is there a standardized mechanism for extracting them?

thanks!


---------------------------------------------------------------------
To unsubscribe, e-mail: embperl-unsubscribe [at] perl
For additional commands, e-mail: embperl-help [at] perl


luiz at engenhosolucoes

Jan 10, 2003, 5:51 AM

Post #4 of 5 (1712 views)
Permalink
Re: question on multipart forms and %fdat [In reply to]

Em Fri, 10 Jan 2003 00:32:55 +0900
Keith Watanabe <keith.watanabe [at] g3s> escreveu:

Hi,

Embperls handles file uploads trough CGI.pm this way when you use
"multipart" forms the file fields are converted in file handles.

In the code bellow it seems that your are reading from the wrong
variable in your object:

> sub upload
> {
> my $self = shift;
> my $file = "$self->{dest}/$self->{file}";

If in $self->{file} you have the "upload" field of the form you should
not use it here this way since it doen not contain just the filename.
In my code I apply the following regex (for a true portable solution you
should use File::Basename):

if ( $fdat{file} =~ /([^\/\\]+)$/ ) {
my $filename = $1;
$filename =~ s/^\.+//; # To prevent hidden files
}

> unlink $file if -e $file;
> open FILE, ">>$file" || die $!;
> my $buffer;
> my $totallength = 0;
> my $bytes;
> while( $bytes = read($self->{file}, $buffer, 1024) )

You have to be sure that in $self->{file} you are really reding from
a reference to $fdat{upload} since its there the magic with CGI.pm.
If you transformed the data it will not work since it will not be a
filehandle anymore. If you need to check and transform the "upload"
field to convert it in a filename you should store a reference to
$fdat{upload} in another instance variable of your object to read from
it later.

> {
> print FILE $buffer;
> $totallength += $bytes;
> }
> close FILE;
> close $self->{file};
> }

Regards,

Luiz Fernando B. Ribeiro
Engenho Soluš§es para a Internet

---------------------------------------------------------------------
To unsubscribe, e-mail: embperl-unsubscribe [at] perl
For additional commands, e-mail: embperl-help [at] perl


keith.watanabe at g3s

Jan 10, 2003, 7:53 AM

Post #5 of 5 (1697 views)
Permalink
Re: question on multipart forms and %fdat [In reply to]

>Embperls handles file uploads trough CGI.pm this way when you use
>"multipart" forms the file fields are converted in file handles.
>
>In the code bellow it seems that your are reading from the wrong
>variable in your object:

actually the thing is that the way my controller handles things, it doesn't
even make the upload call (because it relies on hidden fields that tells
other objects what to instantiate). The main problem i'm seeing is that
%fdat only returns " name" and " filename" keys back. If I have more than
one form field say hidden fields and text fields, those aren't
returned. Here's an example form i wrote up:

<html>
<head>
<title>test</title>
</head>
<body>
<form method="post" enctype="multipart/form-data">
<input type="file" name="image">
<input type="text" name="junk1">
<input type="hidden" name="junk2" value="garbage">
<input type="hidden" name="junk3" value="garbage">
<input type="submit" name="act" value="submit">
<ul>
fdat: [+ %fdat +]<br>
[$ foreach $item keys %fdat $]
<li>item: "[+ $item +]" is "[+ $fdat{$item} +]"<br>
[$ endforeach $]
</ul>
</form>
</body>
</html>

When I attempt to iterate through %fdat, here's the type of output i receive:

fdat: 2/8
item: " name" is ""image""
item: " filename" is ""02071908max_NK116718_b.jpg" Content-Type: image/jpeg
 ě Ó"

(where 02071908max_NK116718_b.jpg is the file upload I'm trying to deal
with). What I want to know is what happens to my other form info like
junk1, junk2, and junk3? When I remove the method="post" part, all of the
fields are displayed correctly. the expected output should've at least
included the hidden and text fields in addition to the file. i'm not
really sure what to make of this.

thanks!

-keith


---------------------------------------------------------------------
To unsubscribe, e-mail: embperl-unsubscribe [at] perl
For additional commands, e-mail: embperl-help [at] perl

ModPerl embperl RSS feed   Index | Next | Previous | View Threaded
 
 


Interested in having your list archived? Contact Gossamer Threads
 
  Web Applications & Managed Hosting Powered by Gossamer Threads Inc.