"Thomas K. Burkholder" <[EMAIL PROTECTED]> writes:

> Hi again,
> 
> Thanks to those who helped me with the install issue.  I've mostly
> resolved that, and now have a new question that seems much more
> mod-perl-ish:
> 
> I have code that does essentially this:
> 
> sub handler {
>   my $r = shift;
>   $r = Apache::Request->new($r);
>   my $handle = $r->upload('filename');
>   my $fh = $handle->fh;
>   ...
> }
> 
> I'd like to write upload code that shows progress (via a fork and
> refresh header trick - don't worry about that).  What I'm wondering is,
> by the time I get $fh above (or even by the time I'm in the handler for
> all I know) do I already have the entire file uploaded, or is it done
> lazily as reads are performed on $fh?  I'm not very good at reading this
> XS stuff, but I looked at libapreq and from that I suspect it's all done
> up front.  Is there any way to read it incrementally?
> 
> Has anyone solved this problem before?  I want to provide an upload
> function for my web app that shows the user periodic progress or maybe
> even allows them to cancel it part way through.  Is this too much of a
> reach for http/mod_perl?

I've managed to do this in the past by modifying mod_proxy on the
front-end server, but I think the ability to do this from within 
Apache::Request would be a nice feature.  Recently David Prosa added 
an upload hook to the C API for libapreq, and yesterday I put together 
a patch to Request.xs that provides a Perl interface.  

It would work something like this:

  my $hook = sub {
    my ($upload, $buf, $len, $data) = @_;
    my $fh = $upload->fh;
    print $fh $buf;
    warn "HOOK_DATA = $data: wrote $len bytes for " . $upload->name;
  }

  my $apr = Apache::Request->new( Apache->request,
                                  HOOK_DATA => "Some parameters",
                                  UPLOAD_HOOK => $hook,
                                );

  my $parm_table = $apr->param;         # causes upload parsing to begin
  my $upload = $apr->upload('file');
  my $fh = $upload->fh;
  ...

In this case, &$hook will be called in place of the normal internal 
(buffered) writes to a temp file.  Note that $upload->fh now
must auto-vivify a temp file if none was created by libapreq itself.
That's probably a feature, but it may require some care if the hook sub 
is poorly designed.  $upload->size will now count the size of the data
sent by the browser, which may or may not be the same as the size of
the temp file (depending on what the hook does with it).  Otherwise
upload objects should behave normally ($upload->fh still dup's and 
seek's outside of the hook sub).

I'll post the diff to the apreq-dev list after I've tested it a bit
more.  Also, please contact me or follow up to the list if anyone has 
some comments/suggestions for improving the API before committing it to
CVS.

Thanks.

-- 
Joe Schaefer

Reply via email to