Getting JPEGs from DB

classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|

Getting JPEGs from DB

Mauro Spivak
Hi there,

I'm have a simple form that uploads files to a server and stores them in a MySQL longblob field using the serialize() function. Then, when I want to retrieve them, I just output them with a couple of headers. Now, because of some reason I don't understand, when I do this through Zend Framework It works perfectly with non-image files (such as PDFs, ZIPs, DOCs, etc.) but not with image files (like JPGs, GIFs, PNGs, etc.)

I'll paste part of the code just for reference:

When uploading: 

{...}
$file['contents'] = file_get_contents($form->file->getValue());
{...}

$newFile = New File;

try {
$newFile->insert($file);
} catch (Exception $e) {
die($e->getMessage());
}


When downloading:

$file = New File;
$file = $file->fetchRow("id='".$params['id']."'");
$this->view->file = $file;

header("Content-Type:image/jpeg");
header("Content-Disposition: attachment; filename=".$file->name.".".MimeToExtension($file->type));

$this->view->file = $file;

I'll really appreciate your answer guys.

Mauro.
Reply | Threaded
Open this post in threaded view
|

Re: Getting JPEGs from DB

Matthew Ratzloff
You really don't want to do this.  Store the files on the file system and keep data about them in the database instead.  Use a rewrite map or, better, a series of rewrite rules to serve the files directly from your web server instead of using passthrough.  That will bypass your problem entirely and be much more scalable.

-Matt

On Wed, Oct 22, 2008 at 7:54 PM, Mauro Spivak <[hidden email]> wrote:
Hi there,

I'm have a simple form that uploads files to a server and stores them in a MySQL longblob field using the serialize() function. Then, when I want to retrieve them, I just output them with a couple of headers. Now, because of some reason I don't understand, when I do this through Zend Framework It works perfectly with non-image files (such as PDFs, ZIPs, DOCs, etc.) but not with image files (like JPGs, GIFs, PNGs, etc.)

I'll paste part of the code just for reference:

When uploading: 

{...}
$file['contents'] = file_get_contents($form->file->getValue());
{...}

$newFile = New File;

try {
$newFile->insert($file);
} catch (Exception $e) {
die($e->getMessage());
}


When downloading:

$file = New File;
$file = $file->fetchRow("id='".$params['id']."'");
$this->view->file = $file;

header("Content-Type:image/jpeg");
header("Content-Disposition: attachment; filename=".$file->name.".".MimeToExtension($file->type));

$this->view->file = $file;

I'll really appreciate your answer guys.

Mauro.

Reply | Threaded
Open this post in threaded view
|

Re: Getting JPEGs from DB

Hector Virgen
In one of my applications I built a thumbnail generator for outputting user avatar images in any size needed, using PHP to resample the original image and using Zend_Cache to cache it.

Here's the tail end of my thumbnail action which I think might help you accomplish what you need. But I agree with Matthew, you're probably better off serving the files directly unless you need PHP to be involved with every served image (logging, resampling, etc.)

--- ImagesController.php ---
<?php

class ImagesController extends Zend_Controller_Action
{
    public function thumbnailAction()
    {
        [ ... ]
        // Last modified timestamps
        $modified = filemtime($cacheFileName);
        $modifiedDateGM = gmdate('D, d M Y H:i:s', $modified) . ' GMT';
        
        // Get request headers to check for cache options
        $headers = apache_request_headers();
        
        if (isset($headers['If-Modified-Since']) && (strtotime($headers['If-Modified-Since']) == $modified)) {
            // Client's cache is current, so we just respond '304 Not Modified'.
            $response->setHeader('Cache-Control', 'max-age=3600, must-revalidate', true);
            $response->setHeader('Last-Modified', $modifiedDateGM, true);
            $response->setHttpResponseCode(304);
        } else {
            // Image not cached or cache outdated, we respond '200 OK' and output the image.
            $response->setHeader('Last-Modified', $modifiedDateGM, true);
            
            // Content type
            $response->setHeader('Content-Type', 'image/png', true);
            
            // Content length
            $response->setHeader('Content-Length', filesize($cacheFileName), true);
            
            // Force binary encoding
            $response->setHeader('Content-Transfer-Encoding', 'binary', true);
            
            // 24 hour cache
            $response->setHeader('Cache-Control', 'max-age=3600, must-revalidate', true);
            
            // Set response body
            $response->setBody(file_get_contents($cacheFileName));
        }
        
        // Send response and exit
        $response->sendResponse();
        exit;
    }
}

On Thu, Oct 23, 2008 at 8:22 AM, Matthew Ratzloff <[hidden email]> wrote:
You really don't want to do this.  Store the files on the file system and keep data about them in the database instead.  Use a rewrite map or, better, a series of rewrite rules to serve the files directly from your web server instead of using passthrough.  That will bypass your problem entirely and be much more scalable.

-Matt


On Wed, Oct 22, 2008 at 7:54 PM, Mauro Spivak <[hidden email]> wrote:
Hi there,

I'm have a simple form that uploads files to a server and stores them in a MySQL longblob field using the serialize() function. Then, when I want to retrieve them, I just output them with a couple of headers. Now, because of some reason I don't understand, when I do this through Zend Framework It works perfectly with non-image files (such as PDFs, ZIPs, DOCs, etc.) but not with image files (like JPGs, GIFs, PNGs, etc.)

I'll paste part of the code just for reference:

When uploading: 

{...}
$file['contents'] = file_get_contents($form->file->getValue());
{...}

$newFile = New File;

try {
$newFile->insert($file);
} catch (Exception $e) {
die($e->getMessage());
}


When downloading:

$file = New File;
$file = $file->fetchRow("id='".$params['id']."'");
$this->view->file = $file;

header("Content-Type:image/jpeg");
header("Content-Disposition: attachment; filename=".$file->name.".".MimeToExtension($file->type));

$this->view->file = $file;

I'll really appreciate your answer guys.

Mauro.




--
-Hector
--
Hector Virgen
Reply | Threaded
Open this post in threaded view
|

Re: Getting JPEGs from DB

BillKarwin
In reply to this post by Matthew Ratzloff

On Oct 23, 2008, at 8:22 AM, Matthew Ratzloff wrote:

> You really don't want to do this.  Store the files on the file  
> system and keep data about them in the database instead.  Use a  
> rewrite map or, better, a series of rewrite rules to serve the files  
> directly from your web server instead of using passthrough.  That  
> will bypass your problem entirely and be much more scalable.
>

There are good reasons for storing images in a BLOB column in the  
database.
There are also good reasons for storing images on the filesystem and  
referencing them by filename.

You shouldn't make unequivocal statements that either solution is  
_always_ better or _always_ worse, without understanding the  
application that the developer is designing.

Thirty lashes with a wet noodle!  :-)

Regards,
Bill Karwin
Reply | Threaded
Open this post in threaded view
|

Re: Getting JPEGs from DB

Matthew Ratzloff
Sort of like your argument against a Zend_Validate_Unique?  ;-D

-Matt

On Thu, Oct 23, 2008 at 9:33 AM, Bill Karwin <[hidden email]> wrote:

On Oct 23, 2008, at 8:22 AM, Matthew Ratzloff wrote:

You really don't want to do this.  Store the files on the file system and keep data about them in the database instead.  Use a rewrite map or, better, a series of rewrite rules to serve the files directly from your web server instead of using passthrough.  That will bypass your problem entirely and be much more scalable.


There are good reasons for storing images in a BLOB column in the database.
There are also good reasons for storing images on the filesystem and referencing them by filename.

You shouldn't make unequivocal statements that either solution is _always_ better or _always_ worse, without understanding the application that the developer is designing.

Thirty lashes with a wet noodle!  :-)

Regards,
Bill Karwin

Reply | Threaded
Open this post in threaded view
|

Re: Getting JPEGs from DB

Michael Crumm
In reply to this post by Hector Virgen
Hector,

Can't believe I found this post, as I attempted to ask a similar question on zf-general yesterday (got not response, surprise..)

I cannot by any means get a controller action to output an image.  I was using a very similar setup, albeit not as many headers, but all i ever get is a blank page.
I added all the headers you are setting to my controller action, but there was no change in output.

If i take a look at firebug's output, it's garbled, but of the correct size.

Here's the header's i'm getting back:
Date    Fri, 24 Oct 2008 11:33:26 GMT
Server    Apache/2.0.63 (CentOS)
X-Powered-By    PHP/5.1.6
Expires    Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control    max-age=3600, must-revalidate
Pragma    no-cache
Last-Modified    Fri, 24 Oct 2008 11:04:47 GMT
Content-Length    132628
Content-Transfer-Encoding    binary
Keep-Alive    timeout=5, max=150
Connection    Keep-Alive
Content-Type    image/jpeg

I'm using 1.6.2 stable


Any thoughts at all would be seriously helpful.  I've hit a total brick wall. 

-Mike





On Thu, Oct 23, 2008 at 10:55 AM, Hector Virgen <[hidden email]> wrote:
In one of my applications I built a thumbnail generator for outputting user avatar images in any size needed, using PHP to resample the original image and using Zend_Cache to cache it.

Here's the tail end of my thumbnail action which I think might help you accomplish what you need. But I agree with Matthew, you're probably better off serving the files directly unless you need PHP to be involved with every served image (logging, resampling, etc.)

--- ImagesController.php ---
<?php

class ImagesController extends Zend_Controller_Action
{
    public function thumbnailAction()
    {
        [ ... ]
        // Last modified timestamps
        $modified = filemtime($cacheFileName);
        $modifiedDateGM = gmdate('D, d M Y H:i:s', $modified) . ' GMT';
        
        // Get request headers to check for cache options
        $headers = apache_request_headers();
        
        if (isset($headers['If-Modified-Since']) && (strtotime($headers['If-Modified-Since']) == $modified)) {
            // Client's cache is current, so we just respond '304 Not Modified'.
            $response->setHeader('Cache-Control', 'max-age=3600, must-revalidate', true);
            $response->setHeader('Last-Modified', $modifiedDateGM, true);
            $response->setHttpResponseCode(304);
        } else {
            // Image not cached or cache outdated, we respond '200 OK' and output the image.
            $response->setHeader('Last-Modified', $modifiedDateGM, true);
            
            // Content type
            $response->setHeader('Content-Type', 'image/png', true);
            
            // Content length
            $response->setHeader('Content-Length', filesize($cacheFileName), true);
            
            // Force binary encoding
            $response->setHeader('Content-Transfer-Encoding', 'binary', true);
            
            // 24 hour cache
            $response->setHeader('Cache-Control', 'max-age=3600, must-revalidate', true);
            
            // Set response body
            $response->setBody(file_get_contents($cacheFileName));
        }
        
        // Send response and exit
        $response->sendResponse();
        exit;
    }
}

On Thu, Oct 23, 2008 at 8:22 AM, Matthew Ratzloff <[hidden email]> wrote:
You really don't want to do this.  Store the files on the file system and keep data about them in the database instead.  Use a rewrite map or, better, a series of rewrite rules to serve the files directly from your web server instead of using passthrough.  That will bypass your problem entirely and be much more scalable.

-Matt


On Wed, Oct 22, 2008 at 7:54 PM, Mauro Spivak <[hidden email]> wrote:
Hi there,

I'm have a simple form that uploads files to a server and stores them in a MySQL longblob field using the serialize() function. Then, when I want to retrieve them, I just output them with a couple of headers. Now, because of some reason I don't understand, when I do this through Zend Framework It works perfectly with non-image files (such as PDFs, ZIPs, DOCs, etc.) but not with image files (like JPGs, GIFs, PNGs, etc.)

I'll paste part of the code just for reference:

When uploading: 

{...}
$file['contents'] = file_get_contents($form->file->getValue());
{...}

$newFile = New File;

try {
$newFile->insert($file);
} catch (Exception $e) {
die($e->getMessage());
}


When downloading:

$file = New File;
$file = $file->fetchRow("id='".$params['id']."'");
$this->view->file = $file;

header("Content-Type:image/jpeg");
header("Content-Disposition: attachment; filename=".$file->name.".".MimeToExtension($file->type));

$this->view->file = $file;

I'll really appreciate your answer guys.

Mauro.




--
-Hector

Reply | Threaded
Open this post in threaded view
|

Re: Getting JPEGs from DB

Hector Virgen
Have you tried clearing or disabling your browser's cache? The headers that I use help ensure that the browser caches the image, but I think if there was an error then you may have bad data in your cache.

When you assign $file to the view, what does the view do with it?

On Fri, Oct 24, 2008 at 4:43 AM, Michael Crumm <[hidden email]> wrote:
Hector,

Can't believe I found this post, as I attempted to ask a similar question on zf-general yesterday (got not response, surprise..)

I cannot by any means get a controller action to output an image.  I was using a very similar setup, albeit not as many headers, but all i ever get is a blank page.
I added all the headers you are setting to my controller action, but there was no change in output.

If i take a look at firebug's output, it's garbled, but of the correct size.

Here's the header's i'm getting back:
Date    Fri, 24 Oct 2008 11:33:26 GMT
Server    Apache/2.0.63 (CentOS)
X-Powered-By    PHP/5.1.6
Expires    Thu, 19 Nov 1981 08:52:00 GMT

Cache-Control    max-age=3600, must-revalidate
Pragma    no-cache
Last-Modified    Fri, 24 Oct 2008 11:04:47 GMT
Content-Length    132628
Content-Transfer-Encoding    binary
Keep-Alive    timeout=5, max=150
Connection    Keep-Alive
Content-Type    image/jpeg

I'm using 1.6.2 stable


Any thoughts at all would be seriously helpful.  I've hit a total brick wall. 

-Mike






On Thu, Oct 23, 2008 at 10:55 AM, Hector Virgen <[hidden email]> wrote:
In one of my applications I built a thumbnail generator for outputting user avatar images in any size needed, using PHP to resample the original image and using Zend_Cache to cache it.

Here's the tail end of my thumbnail action which I think might help you accomplish what you need. But I agree with Matthew, you're probably better off serving the files directly unless you need PHP to be involved with every served image (logging, resampling, etc.)

--- ImagesController.php ---
<?php

class ImagesController extends Zend_Controller_Action
{
    public function thumbnailAction()
    {
        [ ... ]
        // Last modified timestamps
        $modified = filemtime($cacheFileName);
        $modifiedDateGM = gmdate('D, d M Y H:i:s', $modified) . ' GMT';
        
        // Get request headers to check for cache options
        $headers = apache_request_headers();
        
        if (isset($headers['If-Modified-Since']) && (strtotime($headers['If-Modified-Since']) == $modified)) {
            // Client's cache is current, so we just respond '304 Not Modified'.
            $response->setHeader('Cache-Control', 'max-age=3600, must-revalidate', true);
            $response->setHeader('Last-Modified', $modifiedDateGM, true);
            $response->setHttpResponseCode(304);
        } else {
            // Image not cached or cache outdated, we respond '200 OK' and output the image.
            $response->setHeader('Last-Modified', $modifiedDateGM, true);
            
            // Content type
            $response->setHeader('Content-Type', 'image/png', true);
            
            // Content length
            $response->setHeader('Content-Length', filesize($cacheFileName), true);
            
            // Force binary encoding
            $response->setHeader('Content-Transfer-Encoding', 'binary', true);
            
            // 24 hour cache
            $response->setHeader('Cache-Control', 'max-age=3600, must-revalidate', true);
            
            // Set response body
            $response->setBody(file_get_contents($cacheFileName));
        }
        
        // Send response and exit
        $response->sendResponse();
        exit;
    }
}

On Thu, Oct 23, 2008 at 8:22 AM, Matthew Ratzloff <[hidden email]> wrote:
You really don't want to do this.  Store the files on the file system and keep data about them in the database instead.  Use a rewrite map or, better, a series of rewrite rules to serve the files directly from your web server instead of using passthrough.  That will bypass your problem entirely and be much more scalable.

-Matt


On Wed, Oct 22, 2008 at 7:54 PM, Mauro Spivak <[hidden email]> wrote:
Hi there,

I'm have a simple form that uploads files to a server and stores them in a MySQL longblob field using the serialize() function. Then, when I want to retrieve them, I just output them with a couple of headers. Now, because of some reason I don't understand, when I do this through Zend Framework It works perfectly with non-image files (such as PDFs, ZIPs, DOCs, etc.) but not with image files (like JPGs, GIFs, PNGs, etc.)

I'll paste part of the code just for reference:

When uploading: 

{...}
$file['contents'] = file_get_contents($form->file->getValue());
{...}

$newFile = New File;

try {
$newFile->insert($file);
} catch (Exception $e) {
die($e->getMessage());
}


When downloading:

$file = New File;
$file = $file->fetchRow("id='".$params['id']."'");
$this->view->file = $file;

header("Content-Type:image/jpeg");
header("Content-Disposition: attachment; filename=".$file->name.".".MimeToExtension($file->type));

$this->view->file = $file;

I'll really appreciate your answer guys.

Mauro.




--
-Hector




--
-Hector
--
Hector Virgen
Reply | Threaded
Open this post in threaded view
|

Re: Getting JPEGs from DB

Michael Crumm
I tried clearing my browser's cache, but to no effect.
I should have specified the last time around - I only modified my headers to match the ones you were sending when the image was not cached.  I plan on implementing caching, but I want to get this working without first.

I also tried moving the output of the actual image data to the view script, but that also did not change the result.

Here's my current controller action:
    public function viewAction()
    {
        $this->_helper->layout->disableLayout();
        $logo = $this->_logo;
        $modifiedDateGM = gmdate('D, d M Y H:i:s', strtotime($logo['modified'])) . ' GMT';
   
        $response = $this->getFrontController()->getResponse();
        $response->setHeader('Last-Modified', $modifiedDateGM, true);
        $response->setHeader('Content-Type', $logo['type'], true);
        $response->setHeader('Content-Length', $logo['size'], true);
        $response->setHeader('Content-Transfer-Encoding', 'binary', true);
        $response->setHeader('Cache-Control', 'max-age=3600, must-revalidate', true);
        //$response->setBody($logo['data']);
        //$response->sendResponse();
        //exit;

        $this->view->data = $logo['data'];
    }

The commented out lines near the end are from my previous attempt without rendering the view.

Any more ideas?

-Mike



On Fri, Oct 24, 2008 at 10:33 AM, Hector Virgen <[hidden email]> wrote:
Have you tried clearing or disabling your browser's cache? The headers that I use help ensure that the browser caches the image, but I think if there was an error then you may have bad data in your cache.

When you assign $file to the view, what does the view do with it?


On Fri, Oct 24, 2008 at 4:43 AM, Michael Crumm <[hidden email]> wrote:
Hector,

Can't believe I found this post, as I attempted to ask a similar question on zf-general yesterday (got not response, surprise..)

I cannot by any means get a controller action to output an image.  I was using a very similar setup, albeit not as many headers, but all i ever get is a blank page.
I added all the headers you are setting to my controller action, but there was no change in output.

If i take a look at firebug's output, it's garbled, but of the correct size.

Here's the header's i'm getting back:
Date    Fri, 24 Oct 2008 11:33:26 GMT
Server    Apache/2.0.63 (CentOS)
X-Powered-By    PHP/5.1.6
Expires    Thu, 19 Nov 1981 08:52:00 GMT

Cache-Control    max-age=3600, must-revalidate
Pragma    no-cache
Last-Modified    Fri, 24 Oct 2008 11:04:47 GMT
Content-Length    132628
Content-Transfer-Encoding    binary
Keep-Alive    timeout=5, max=150
Connection    Keep-Alive
Content-Type    image/jpeg

I'm using 1.6.2 stable


Any thoughts at all would be seriously helpful.  I've hit a total brick wall. 

-Mike






On Thu, Oct 23, 2008 at 10:55 AM, Hector Virgen <[hidden email]> wrote:
In one of my applications I built a thumbnail generator for outputting user avatar images in any size needed, using PHP to resample the original image and using Zend_Cache to cache it.

Here's the tail end of my thumbnail action which I think might help you accomplish what you need. But I agree with Matthew, you're probably better off serving the files directly unless you need PHP to be involved with every served image (logging, resampling, etc.)

--- ImagesController.php ---
<?php

class ImagesController extends Zend_Controller_Action
{
    public function thumbnailAction()
    {
        [ ... ]
        // Last modified timestamps
        $modified = filemtime($cacheFileName);
        $modifiedDateGM = gmdate('D, d M Y H:i:s', $modified) . ' GMT';
        
        // Get request headers to check for cache options
        $headers = apache_request_headers();
        
        if (isset($headers['If-Modified-Since']) && (strtotime($headers['If-Modified-Since']) == $modified)) {
            // Client's cache is current, so we just respond '304 Not Modified'.
            $response->setHeader('Cache-Control', 'max-age=3600, must-revalidate', true);
            $response->setHeader('Last-Modified', $modifiedDateGM, true);
            $response->setHttpResponseCode(304);
        } else {
            // Image not cached or cache outdated, we respond '200 OK' and output the image.
            $response->setHeader('Last-Modified', $modifiedDateGM, true);
            
            // Content type
            $response->setHeader('Content-Type', 'image/png', true);
            
            // Content length
            $response->setHeader('Content-Length', filesize($cacheFileName), true);
            
            // Force binary encoding
            $response->setHeader('Content-Transfer-Encoding', 'binary', true);
            
            // 24 hour cache
            $response->setHeader('Cache-Control', 'max-age=3600, must-revalidate', true);
            
            // Set response body
            $response->setBody(file_get_contents($cacheFileName));
        }
        
        // Send response and exit
        $response->sendResponse();
        exit;
    }
}

On Thu, Oct 23, 2008 at 8:22 AM, Matthew Ratzloff <[hidden email]> wrote:
You really don't want to do this.  Store the files on the file system and keep data about them in the database instead.  Use a rewrite map or, better, a series of rewrite rules to serve the files directly from your web server instead of using passthrough.  That will bypass your problem entirely and be much more scalable.

-Matt


On Wed, Oct 22, 2008 at 7:54 PM, Mauro Spivak <[hidden email]> wrote:
Hi there,

I'm have a simple form that uploads files to a server and stores them in a MySQL longblob field using the serialize() function. Then, when I want to retrieve them, I just output them with a couple of headers. Now, because of some reason I don't understand, when I do this through Zend Framework It works perfectly with non-image files (such as PDFs, ZIPs, DOCs, etc.) but not with image files (like JPGs, GIFs, PNGs, etc.)

I'll paste part of the code just for reference:

When uploading: 

{...}
$file['contents'] = file_get_contents($form->file->getValue());
{...}

$newFile = New File;

try {
$newFile->insert($file);
} catch (Exception $e) {
die($e->getMessage());
}


When downloading:

$file = New File;
$file = $file->fetchRow("id='".$params['id']."'");
$this->view->file = $file;

header("Content-Type:image/jpeg");
header("Content-Disposition: attachment; filename=".$file->name.".".MimeToExtension($file->type));

$this->view->file = $file;

I'll really appreciate your answer guys.

Mauro.




--
-Hector




--
-Hector

Reply | Threaded
Open this post in threaded view
|

Re: Getting JPEGs from DB

Hector Virgen
It appears that your controller code should work, so maybe you have bad data? It's hard to say.

What character set are you using for the table and data column?

On Fri, Oct 24, 2008 at 3:06 PM, Michael Crumm <[hidden email]> wrote:
I tried clearing my browser's cache, but to no effect.
I should have specified the last time around - I only modified my headers to match the ones you were sending when the image was not cached.  I plan on implementing caching, but I want to get this working without first.

I also tried moving the output of the actual image data to the view script, but that also did not change the result.

Here's my current controller action:
    public function viewAction()
    {
        $this->_helper->layout->disableLayout();
        $logo = $this->_logo;
        $modifiedDateGM = gmdate('D, d M Y H:i:s', strtotime($logo['modified'])) . ' GMT';
   
        $response = $this->getFrontController()->getResponse();

        $response->setHeader('Last-Modified', $modifiedDateGM, true);
        $response->setHeader('Content-Type', $logo['type'], true);
        $response->setHeader('Content-Length', $logo['size'], true);

        $response->setHeader('Content-Transfer-Encoding', 'binary', true);
        $response->setHeader('Cache-Control', 'max-age=3600, must-revalidate', true);
        //$response->setBody($logo['data']);
        //$response->sendResponse();
        //exit;

        $this->view->data = $logo['data'];
    }

The commented out lines near the end are from my previous attempt without rendering the view.

Any more ideas?

-Mike




On Fri, Oct 24, 2008 at 10:33 AM, Hector Virgen <[hidden email]> wrote:
Have you tried clearing or disabling your browser's cache? The headers that I use help ensure that the browser caches the image, but I think if there was an error then you may have bad data in your cache.

When you assign $file to the view, what does the view do with it?


On Fri, Oct 24, 2008 at 4:43 AM, Michael Crumm <[hidden email]> wrote:
Hector,

Can't believe I found this post, as I attempted to ask a similar question on zf-general yesterday (got not response, surprise..)

I cannot by any means get a controller action to output an image.  I was using a very similar setup, albeit not as many headers, but all i ever get is a blank page.
I added all the headers you are setting to my controller action, but there was no change in output.

If i take a look at firebug's output, it's garbled, but of the correct size.

Here's the header's i'm getting back:
Date    Fri, 24 Oct 2008 11:33:26 GMT
Server    Apache/2.0.63 (CentOS)
X-Powered-By    PHP/5.1.6
Expires    Thu, 19 Nov 1981 08:52:00 GMT

Cache-Control    max-age=3600, must-revalidate
Pragma    no-cache
Last-Modified    Fri, 24 Oct 2008 11:04:47 GMT
Content-Length    132628
Content-Transfer-Encoding    binary
Keep-Alive    timeout=5, max=150
Connection    Keep-Alive
Content-Type    image/jpeg

I'm using 1.6.2 stable


Any thoughts at all would be seriously helpful.  I've hit a total brick wall. 

-Mike






On Thu, Oct 23, 2008 at 10:55 AM, Hector Virgen <[hidden email]> wrote:
In one of my applications I built a thumbnail generator for outputting user avatar images in any size needed, using PHP to resample the original image and using Zend_Cache to cache it.

Here's the tail end of my thumbnail action which I think might help you accomplish what you need. But I agree with Matthew, you're probably better off serving the files directly unless you need PHP to be involved with every served image (logging, resampling, etc.)

--- ImagesController.php ---
<?php

class ImagesController extends Zend_Controller_Action
{
    public function thumbnailAction()
    {
        [ ... ]
        // Last modified timestamps
        $modified = filemtime($cacheFileName);
        $modifiedDateGM = gmdate('D, d M Y H:i:s', $modified) . ' GMT';
        
        // Get request headers to check for cache options
        $headers = apache_request_headers();
        
        if (isset($headers['If-Modified-Since']) && (strtotime($headers['If-Modified-Since']) == $modified)) {
            // Client's cache is current, so we just respond '304 Not Modified'.
            $response->setHeader('Cache-Control', 'max-age=3600, must-revalidate', true);
            $response->setHeader('Last-Modified', $modifiedDateGM, true);
            $response->setHttpResponseCode(304);
        } else {
            // Image not cached or cache outdated, we respond '200 OK' and output the image.
            $response->setHeader('Last-Modified', $modifiedDateGM, true);
            
            // Content type
            $response->setHeader('Content-Type', 'image/png', true);
            
            // Content length
            $response->setHeader('Content-Length', filesize($cacheFileName), true);
            
            // Force binary encoding
            $response->setHeader('Content-Transfer-Encoding', 'binary', true);
            
            // 24 hour cache
            $response->setHeader('Cache-Control', 'max-age=3600, must-revalidate', true);
            
            // Set response body
            $response->setBody(file_get_contents($cacheFileName));
        }
        
        // Send response and exit
        $response->sendResponse();
        exit;
    }
}

On Thu, Oct 23, 2008 at 8:22 AM, Matthew Ratzloff <[hidden email]> wrote:
You really don't want to do this.  Store the files on the file system and keep data about them in the database instead.  Use a rewrite map or, better, a series of rewrite rules to serve the files directly from your web server instead of using passthrough.  That will bypass your problem entirely and be much more scalable.

-Matt


On Wed, Oct 22, 2008 at 7:54 PM, Mauro Spivak <[hidden email]> wrote:
Hi there,

I'm have a simple form that uploads files to a server and stores them in a MySQL longblob field using the serialize() function. Then, when I want to retrieve them, I just output them with a couple of headers. Now, because of some reason I don't understand, when I do this through Zend Framework It works perfectly with non-image files (such as PDFs, ZIPs, DOCs, etc.) but not with image files (like JPGs, GIFs, PNGs, etc.)

I'll paste part of the code just for reference:

When uploading: 

{...}
$file['contents'] = file_get_contents($form->file->getValue());
{...}

$newFile = New File;

try {
$newFile->insert($file);
} catch (Exception $e) {
die($e->getMessage());
}


When downloading:

$file = New File;
$file = $file->fetchRow("id='".$params['id']."'");
$this->view->file = $file;

header("Content-Type:image/jpeg");
header("Content-Disposition: attachment; filename=".$file->name.".".MimeToExtension($file->type));

$this->view->file = $file;

I'll really appreciate your answer guys.

Mauro.




--
-Hector




--
-Hector




--
-Hector
--
Hector Virgen
Reply | Threaded
Open this post in threaded view
|

Re: Getting JPEGs from DB

Michael Crumm
Hector,

I was able to verify that controller code as functional by moving it out of my project and into a test one.
I believe now that my issue lies somewhere in my bootstrap or initialization plugin.

If i every figure out what in the world is going on, I will post my solution.

Thanks everyone for the help!

-Mike

On Fri, Oct 24, 2008 at 7:08 PM, Hector Virgen <[hidden email]> wrote:
It appears that your controller code should work, so maybe you have bad data? It's hard to say.

What character set are you using for the table and data column?


On Fri, Oct 24, 2008 at 3:06 PM, Michael Crumm <[hidden email]> wrote:
I tried clearing my browser's cache, but to no effect.
I should have specified the last time around - I only modified my headers to match the ones you were sending when the image was not cached.  I plan on implementing caching, but I want to get this working without first.

I also tried moving the output of the actual image data to the view script, but that also did not change the result.

Here's my current controller action:
    public function viewAction()
    {
        $this->_helper->layout->disableLayout();
        $logo = $this->_logo;
        $modifiedDateGM = gmdate('D, d M Y H:i:s', strtotime($logo['modified'])) . ' GMT';
   
        $response = $this->getFrontController()->getResponse();

        $response->setHeader('Last-Modified', $modifiedDateGM, true);
        $response->setHeader('Content-Type', $logo['type'], true);
        $response->setHeader('Content-Length', $logo['size'], true);

        $response->setHeader('Content-Transfer-Encoding', 'binary', true);
        $response->setHeader('Cache-Control', 'max-age=3600, must-revalidate', true);
        //$response->setBody($logo['data']);
        //$response->sendResponse();
        //exit;

        $this->view->data = $logo['data'];
    }

The commented out lines near the end are from my previous attempt without rendering the view.

Any more ideas?

-Mike




On Fri, Oct 24, 2008 at 10:33 AM, Hector Virgen <[hidden email]> wrote:
Have you tried clearing or disabling your browser's cache? The headers that I use help ensure that the browser caches the image, but I think if there was an error then you may have bad data in your cache.

When you assign $file to the view, what does the view do with it?


On Fri, Oct 24, 2008 at 4:43 AM, Michael Crumm <[hidden email]> wrote:
Hector,

Can't believe I found this post, as I attempted to ask a similar question on zf-general yesterday (got not response, surprise..)

I cannot by any means get a controller action to output an image.  I was using a very similar setup, albeit not as many headers, but all i ever get is a blank page.
I added all the headers you are setting to my controller action, but there was no change in output.

If i take a look at firebug's output, it's garbled, but of the correct size.

Here's the header's i'm getting back:
Date    Fri, 24 Oct 2008 11:33:26 GMT
Server    Apache/2.0.63 (CentOS)
X-Powered-By    PHP/5.1.6
Expires    Thu, 19 Nov 1981 08:52:00 GMT

Cache-Control    max-age=3600, must-revalidate
Pragma    no-cache
Last-Modified    Fri, 24 Oct 2008 11:04:47 GMT
Content-Length    132628
Content-Transfer-Encoding    binary
Keep-Alive    timeout=5, max=150
Connection    Keep-Alive
Content-Type    image/jpeg

I'm using 1.6.2 stable


Any thoughts at all would be seriously helpful.  I've hit a total brick wall. 

-Mike






On Thu, Oct 23, 2008 at 10:55 AM, Hector Virgen <[hidden email]> wrote:
In one of my applications I built a thumbnail generator for outputting user avatar images in any size needed, using PHP to resample the original image and using Zend_Cache to cache it.

Here's the tail end of my thumbnail action which I think might help you accomplish what you need. But I agree with Matthew, you're probably better off serving the files directly unless you need PHP to be involved with every served image (logging, resampling, etc.)

--- ImagesController.php ---
<?php

class ImagesController extends Zend_Controller_Action
{
    public function thumbnailAction()
    {
        [ ... ]
        // Last modified timestamps
        $modified = filemtime($cacheFileName);
        $modifiedDateGM = gmdate('D, d M Y H:i:s', $modified) . ' GMT';
        
        // Get request headers to check for cache options
        $headers = apache_request_headers();
        
        if (isset($headers['If-Modified-Since']) && (strtotime($headers['If-Modified-Since']) == $modified)) {
            // Client's cache is current, so we just respond '304 Not Modified'.
            $response->setHeader('Cache-Control', 'max-age=3600, must-revalidate', true);
            $response->setHeader('Last-Modified', $modifiedDateGM, true);
            $response->setHttpResponseCode(304);
        } else {
            // Image not cached or cache outdated, we respond '200 OK' and output the image.
            $response->setHeader('Last-Modified', $modifiedDateGM, true);
            
            // Content type
            $response->setHeader('Content-Type', 'image/png', true);
            
            // Content length
            $response->setHeader('Content-Length', filesize($cacheFileName), true);
            
            // Force binary encoding
            $response->setHeader('Content-Transfer-Encoding', 'binary', true);
            
            // 24 hour cache
            $response->setHeader('Cache-Control', 'max-age=3600, must-revalidate', true);
            
            // Set response body
            $response->setBody(file_get_contents($cacheFileName));
        }
        
        // Send response and exit
        $response->sendResponse();
        exit;
    }
}

On Thu, Oct 23, 2008 at 8:22 AM, Matthew Ratzloff <[hidden email]> wrote:
You really don't want to do this.  Store the files on the file system and keep data about them in the database instead.  Use a rewrite map or, better, a series of rewrite rules to serve the files directly from your web server instead of using passthrough.  That will bypass your problem entirely and be much more scalable.

-Matt


On Wed, Oct 22, 2008 at 7:54 PM, Mauro Spivak <[hidden email]> wrote:
Hi there,

I'm have a simple form that uploads files to a server and stores them in a MySQL longblob field using the serialize() function. Then, when I want to retrieve them, I just output them with a couple of headers. Now, because of some reason I don't understand, when I do this through Zend Framework It works perfectly with non-image files (such as PDFs, ZIPs, DOCs, etc.) but not with image files (like JPGs, GIFs, PNGs, etc.)

I'll paste part of the code just for reference:

When uploading: 

{...}
$file['contents'] = file_get_contents($form->file->getValue());
{...}

$newFile = New File;

try {
$newFile->insert($file);
} catch (Exception $e) {
die($e->getMessage());
}


When downloading:

$file = New File;
$file = $file->fetchRow("id='".$params['id']."'");
$this->view->file = $file;

header("Content-Type:image/jpeg");
header("Content-Disposition: attachment; filename=".$file->name.".".MimeToExtension($file->type));

$this->view->file = $file;

I'll really appreciate your answer guys.

Mauro.




--
-Hector




--
-Hector




--
-Hector