[Catalyst] Downloading BLOBs

Toby Corkindale toby at ymogen.net
Tue May 9 15:16:14 CEST 2006


(This is related to my discussion of BLOBs via DBIx::Class on their list)

Given a $c->stash->{content_oid} that contains a PostgreSQL OID for a 
large object, this should cause Catalyst::Engine to send it to the 
client without slurping the entire contents into ram:

sub finalize_body {
     my $c = shift;

     if (defined $c->stash->{'content_oid'}) {
         $c->log->debug("In custom finalize_body() routine..");
         # This handle should be a Postgres large object ID
         my $oid = $c->stash->{'content_oid'};
         my $dbh = $c->model('DB')->schema->storage->dbh;

         $c->model('DB')->schema->txn_begin;
             my $io = IO::BLOB::Pg->new($dbh, $oid);
             die("Failed to create IO::BLOB::Pg") unless defined $io;
             $c->response->body($io);
             $c->NEXT::finalize_body;
         $c->model('DB')->schema->txn_commit;
     }
     else {
         $c->NEXT::finalize_body;
     }
     return $c;
}


It's rather hacky, but I thought I'd submit it for your comments.

I'll try and create a DBIx::Class::..::BLOB interface at some point, and 
if I do, I'll definately arrange it so it hopefully doesn't require the 
hacky transaction-surrounding bits.

Also, I have a bad feeling about doing the transaction with 
begin/commit, rather than the txn_do( sub {} ) method.. However, that's 
not available, due to NEXT not functioning within an anonymous sub (of 
course).

An alternative is to just call $c->engine->finalize_body( $c, @_ ); 
inside the txn_do() sub, instead of NEXTing onto it. I think I prefer 
that method, since it allows us to end the transaction in case of 
death.. but it breaks any other plugins.

$c->model('DB')->schema->txn_do( sub {
     my $io = IO::BLOB::Pg->new($dbh, $oid);
     die("Failed to create IO::BLOB::Pg") unless defined $io;
     $c->response->body($io);
     $c->engine->finalize_body( $c, @_ );
});


Any suggestions?
(It seems like "write the D::C plugin already" is the neat solution, 
although I won't ahve time to do that immediately)

Cheers,
Toby



More information about the Catalyst mailing list