Spruce interactive

Noise

Serving Large Downloadable Files with WP e-Commerce

Posted: May 30th, 2012

Author: Ben Heller

Tags:

, , , , ,

 Details

WP e-Commerce has a reputation among WordPress developers as a flexible and feature-rich shopping cart solution that integrates well with new or existing sites. Alas, in the rush to roll out new features, the plugin’s developers have ignored numerous bugs that affect both core and extended functionality, they’ve written shortcodes that lead to empty or nonexistent functions, they’ve done away with proper error handling, and left us alone in the universe with woefully outdated documentation. Nevertheless, it remains the best free e-commerce solution for WordPress, and we’ve decided to use it on a number of our clients’ sites. Truth & Soul RecordsThe Bad Version, and Goddess of the Hunt are all powered by heavily customized WPEC installations. In an effort to provide our clients with a smooth online sales experience and a rich feature set, we’ve taken it upon ourselves to improve on WPEC’s default functionality.

While working on Truth & Soul Records, we encountered an issue with large file downloads. This particular client wished to serve whole album downloads as WAV files, with sizes as large as 1GB. WP e-Commerce currently (version 3.8.8.1 as of this posting) loads files into the output buffer and serves them using the wpsc_readfile_chunked function in wpsc-includes/misc.functions.php. This is all fine and dandy until the size of the file exceeds the size of your server’s php memory limit. When this happens, the download stops with no warning and the user is left with a corrupt file. No good. The key to success is to use a different method of serving the files such that the entire content of the download need not be loaded into memory.

In wpsc-includes/ajax.functions.php around line 1046 is a conditional statement that reads:

if ( is_file( $file_path ) ) {
  if( !ini_get('safe_mode') ) set_time_limit(0);
  header( 'Content-Type: ' . $file_data->post_mime_type );
  header( 'Content-Length: ' . filesize( $file_path ) );
  header( 'Content-Transfer-Encoding: binary' );
  header( 'Content-Disposition: attachment; filename="' . stripslashes( $file_name ) . '"' );
  if ( isset( $_SERVER["HTTPS"] ) && ($_SERVER["HTTPS"] != '') ) {
    header( "Pragma: public" );
    header( "Expires: 0" );
    header( "Cache-Control: must-revalidate, post-check=0, pre-check=0" );
    header( "Cache-Control: public" );
  } else {
    header( 'Cache-Control: must-revalidate, post-check=0, pre-check=0' );
  }
  header( "Pragma: public" );
  header( "Expires: 0" );

  session_destroy();
  wpsc_readfile_chunked( $file_path );
  exit();
}

We’ve simplified this to:
if ( is_file( $file_path ) ) {
   header( 'Content-Type: ' . $file_data->post_mime_type );
   header( 'Content-Length: ' . filesize( $file_path ) );
   header( 'Content-Disposition: attachment; filename="' . stripslashes( $file_name ) . '"' );
   header ('X-Sendfile: ' . $file_path);
   exit();
}

This was accomplished using the Apache X-SendFile module (mod_xsendfile). It’s astonishingly easy to install:

  1. Grab the source.
  2. Compile and install: path/to/apxs -cia mod_xsendfile.c
  3. Add LoadModule xsendfile_module /path/to/modules/mod_xsendfile.so and XSendFile on to your httpd.conf file (on separate lines)
  4. Restart apache

If you’re running Apache’s leaner cousin Lighttpd, there’s a good chance you ready have X-SendFile enabled by default. That said, the availability of this module will vary based on your hosting provider and level of service. Users on VPS and dedicated hosting plans should have no trouble, while users in shared hosting situations may need to contact their hosting provider to enable X-SendFile. We’re delighted to have found this simple solution to such a frustrating problem, so if you’re reading this and would like our assistance in implementing this fix, don’t hesitate to get in touch.

  • http://www.freelancehyderabad.com/ freelance web designer

    very useful article , i need this source for my project thanks for sharing

  • Michelle

    Hey

    I jsut wanted to say thanks for the great posts on WPEC I am part of the GetShopped team and will be directing customers to these posts for sure!
    As for your comments on WPEC I totally agree in terms of bugs and documentation etc… we have a new team of developers now and we hear you guys! 3.8.9 is going to be out soon and i think you will all be presently surprised with the changelog :)

    Thanks again for the great posts this post here might be of interest to you and we would love for you to join our network: http://getshopped.org/developers/are-you-a-wpec-developer-heads-up-the-bold-future-of-wp-e-commerce/

    • spruceit

      Thanks Michelle! We signed up for your developer network, and look forward to seeing the next generation WPEC!

  • Dime

    Hi & many thanks for this article ! Is it possible to get any additional information from you guys on steps 2 – 4 of the manual

    • spruceit

      Heya! These steps vary based on your operating system. Usually the best approach is to Google each step + your OS to get specialized instructions. For example, “How to restart Apache in CentOS 5.1″ will yield results for your specific system.

  • Oliver

    Hi, thanks for this. I’m serving downloads via amazon s3 and wpec. I applied the change and download is working fine. But still have the problem of admin area being completely unresponsive while a download is taking place (which also happened before applying the above patch). Have you encountered this problem?

    • Oliver

      Actually I’ve noticed that it’s only slow if logged in with the same browser that is performing the download.

      • spruceit

        Hi Oliver–I’m afraid we haven’t experienced this issue! Also, you shouldn’t need to apply this patch if you’re serving downloads via S3, so that might be part of the problem. The X-Sendfile method should only be needed if the downloads are coming from your local server.

Talk to Us

Wise men have said, "All good things must come to an end", and so it was with Spruce. We began our first project in 2006, and completed our last in Fall 2013. It's been a wonderful experience, but now it's time to begin the next adventure.

Though...we wouldn't want to leave you hanging, now would we? Here are our top recommendations for world-class branding, design, and web development:

  • Kristina (KJ) Parish and Beam Collective:
    KJ provided the artistic vision that allowed Spruce to succeed, and we still think she's the greatest designer in the entire world. She's started a new collective with some talented developers, and is covering much the same territory as Spruce--design and development all under one roof, with a caliber of service and professionalism seldom seen in this business or any other. If you like what you see on the Spruce site, then definitely get in touch with KJ at kj@beamcollective.com
  • Permanent Art & Design
    Permanent is a nationally recognized design & branding firm out of Minneapolis, MN. They've been a long term collaborator and strategic partner over the past couple years, and we'd recommend them for medium to large sized businesses/organizations who are serious about putting their best foot forward. In addition to design, Permanent offers strategy and marketing services, plus in-house and networked developers. For more information contact Joseph Belk joseph@permanentadg.com
  • Nate Thompson
    A freelancer, Nate reminds us of ourselves back in the day. Smart, communicative, and skilled, Nate is our recommendation for small to medium sized businesses/organizations who have sites built on Wordpress or other open source content management solutions. With a background in both design and development, he's a one-stop shop for most web-related tasks. You can get in touch at nate.a.thompson@gmail.com
  • Kevin DeBernardi
    Designer turned developer, Kevin is embarking on a freelance web career after working as the in-house designer at the Museum of the City of New York. He's adept at translating his design ideas into custom PHP code, and is constantly expanding his technical palette. Kevin's a good choice for projects that don't quite fit into the Wordpress mold, and that would benefit from a consistency of presence and vision from design through execution. Kevin can be reached at kevin@analoglifestyle.com