[Catalyst] Download a file - Catalyst Docs 'Cookbook' example doesn't work

Matthew Braid catalyst at mdb.id.au
Fri Nov 12 00:39:52 GMT 2010


Hi,

OK, tried that (and it makes sense, even though I was hoping there was
some nicer command to say "don't forward to any view", but hey) and no
dice. My download method now has:

  $c->stash->{ctrl}{view_handled} = 1;

and Root's end method is now:

sub end : ActionClass('RenderView') {
  my ($self, $c) = @_;
  $c->log->debug("END: VIEW HANDLED IS " . $c->stash->{ctrl}{view_handled});
  return 1 if $c->stash->{ctrl}{view_handled};
}

but it still appends an error page to the download (and the debug
output still has '[debug] Rendering template "file/get.tt"', which it
shouldn't be trying).

According to the Catalyst::Action::RenderView docs, the view shouldn't
be forwarded to if:

  1) The response code is 3XX
  2) The response code is 204 (no content)
  3) $c->res->body has already been set

It doesn't actually mention different behaviour depending on what the
method's return value is.

Oddly, I would have thought $c->res->write would be equivalent to
setting the body. As it turns out, if I add:

  $c->res->body('X');

to the end of my download method, it does indeed only append an 'X'
instead of an error message. Sadly, replacing 'X' with an empty string
does not work the same way, so I'm guessing "$c->res->body has already
been set" should actually read "$c->res->body is not undef or an empty
string".

So in the end I have had to add:

  $c->res->code(204);

to the end of the download method, which seems to do the trick.

MB


On Thu, Nov 11, 2010 at 5:39 PM, Kieren Diment <diment at gmail.com> wrote:
> I'd be inclined to do set $c->stash( served_file => 1) if one of these files is served
>
> then avoid forwarding to the view if this stash key is set in MyApp.pm with the following:
>
> sub end : ActionClass('RenderView') {
>        my ($self, $c);
>        return 1 if $c->stash(served_file);
> }
>
> See the docs for Catalyst::Action::RenderView for details.
>
> On 11/11/2010, at 5:33 PM, Matthew Braid wrote:
>
>> Hi all,
>>
>> Part of the site I'm writing includes the ability to download certain
>> files. These files can be large, so going from the cookbook method at
>> http://search.cpan.org/~zarquon/Catalyst-Manual-5.8005/lib/Catalyst/Manual/Cookbook.pod#Forcing_the_browser_to_download_content,
>> I modified it so that the download code was (chopped down code ahead):
>>
>>    my $fh = handle_of_file_content(); # Pseudo
>>    my $filename = $c->stash->{file}->fname;
>>    $c->res->header('Content-Disposition', qq[attachment;
>> filename="$filename"]);
>>    $c->res->body($fh);
>>
>> According to the docs, this should download the file (the filehandle
>> should be read chunk by chunk and all will be well). Unfortunately
>> instead the following happens:
>>
>>  1) The browser always identifies the content as a "HTML File"
>>  2) Only a small chunk of the file is actually downloaded.
>>
>> So I made another change and decided to use the response object's
>> write method like so:
>>
>>  my $fh = handle_of_file_content(); # Pseudo
>>  my $filename = $c->stash->{file}->fname;
>>  $c->res->header('Content-Disposition', qq[attachment; filename="$filename"]);
>>  while (defined(my $line = <$fh>)) {
>>    $c->res->write($line);
>>  }
>>  close($fh);
>>
>> This almost works as well - the browser identifies the file type
>> correctly, and the whole file is downloaded.
>>
>> Unfortunately the file has a Catalyst error page appended (the error
>> is it can't find the default template). I'm assuming this is because
>> once the action is handled it still goes to the default View and tries
>> to render a page.
>>
>> So, am I doing something horribly wrong, or do I just need the magic
>> words that say "Do not forward to the default view"? I'm hoping the
>> latter, and I'm hoping it's something blindingly obvious and my brain
>> is just running slow today.
>>
>> TIA,
>> MB
>>
>> _______________________________________________
>> List: Catalyst at lists.scsys.co.uk
>> Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
>> Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/
>> Dev site: http://dev.catalyst.perl.org/
>
>
> _______________________________________________
> List: Catalyst at lists.scsys.co.uk
> Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
> Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/
> Dev site: http://dev.catalyst.perl.org/
>



More information about the Catalyst mailing list