A Programmer’s Perspective twitter
A Programmer’s Perspective Rss

PHP File Streaming with cat and passthru

Posted by Jason | Posted in linux, mysql, php | Posted on 09-11-2009

3

The problem

This weekend, I needed to figure out how to make an on-request, downloadable, backup of an entire MySQL database (for Magento, in case you were wondering).
At first, I attempted the simplest approach, which was to perform the backup via system() or exec(), and then serve the file as a download using either file_get_contents or fopen/fread, etc. This wouldn’t work because PHP would run out of memory when reading the file. I even tried stream_get_contents() with the same result.

Hmmm….

I’m sure there are other ways of getting this done, but my approach has been working flawlessly so far and I thought I’d share with you.

The solution

Here is the entire code segment which performs the backup, bzips the SQL file, then serves it as a download using passthru and cat.


//Define where backup will go
$backup_folder = getenv("DOCUMENT_ROOT") . $settings['base_url'] . '/backup/';
$backup_file = 'aps_backup_' . date("Y-m-d-H-i-s") . '.sql.bz2';
$backupFile = $backup_folder . $backup_file;

//Perform the database backup
$command = "mysqldump --opt -h$dbhost -u$dbuser -p$dbpass $dbname | bzip2 > $backupFile";
error_log("Executing: $command");
exec($command);

//Serve file as download
header("Content-type: application/octet-stream");
header("Content-Disposition: attachment; filename=\"$backup_file\"");
passthru("cat $backupFile");

As you can see, the database backup command is executed, and the output is bzipped and stored in the “backup” folder.
Once the command is completed, the headers are setup to serve a file download, and using the passthru command, we simply cat the file.
This effectively streams the file as a download, thus alleviating the memory limit errors I was receiving when trying to open/read/serve the large file download.
Obviously, this wouldn’t work on Windows.

I’m curious if anyone else has been faced with this problem, and what your solution(s) were?

PHPMailer Inline String Attachment

Posted by Jason | Posted in mysql, php | Posted on 09-09-2009

1

Recently, while using PHPMailer, I needed the ability to have an inline string attachment, however this functionality is not present as of version 5.0.2, so I wrote my own.

For those who don’t know, PHPMailer has a number of ways you can create email attachments:

  • Standard Attachment – works as you’d expect
  • Inline Attachment – attachments you can reference in the message body. For instance, if you attach an image, you can then reference that image using the IMG tag in the body
  • String Attachment – builds an attachment from blob data (usually stored in a database)

Inline attachments and String attachments rock, however there was no combination of the two. So, I wrote one. Simply add this block of code to your phpmailer class and you’re good to go.


/**
* Adds a string or binary attachment (non-filesystem) to the list.
* This method can be used to attach ascii or binary data,
* such as a BLOB record from a database.
* @param string $string String attachment data.
* @param string $cid Content ID of the attachment. Use this to identify
* the Id for accessing the image in an HTML form.
* @param string $filename Name of the attachment.
* @param string $encoding File encoding (see $Encoding).
* @param string $type File extension (MIME) type.
* @return void
*/
public function AddInlineStringAttachment($string, $cid, $filename, $encoding = 'base64', $type = 'application/octet-stream') {
// Append to $attachment array
$this->attachment[] = array(
0 => $string,
1 => $filename,
2 => $filename,
3 => $encoding,
4 => $type,
5 => true, // isStringAttachment
6 => 'inline',
7 => $cid
);
}

Wordpress API

Posted by Jason | Posted in php | Posted on 05-07-2009

4

Recently I’ve gotten into Wordpress plugin development. I’ve created a few plugins for clients that include widgets, settings pages, and hooks into several actions. However, one thing I’ve not yet been able to figure out is how to encrypt settings page options. Has anyone done this?

There are currently a few ways to create settings pages. You can either write out the entire form, or you can create sections and fields using the API. Each option, however, utilizes get_option() to show the current value.

This is fine, however there is no API function (that I’ve found) that runs BEFORE an option is updated. The only function I have right now is update_option_(the_option)(). But, this runs AFTER the update has already happened. So, if I wanted to encrypt those options using server-side encryption, I would enter into an infinite loop since I’d be calling update_option_(the_option)() over and over again.

Has anyone ever encrypted settings page option values before? If so, how do you go about doing it properly?

I’m sure I can hack together a solution that encrypts & decrypts the values using Javascript on the form, but that just seems dirty to me.

I’d be interested to hear if anyone else has had this problem.

Javascript Minifier

Posted by Jason | Posted in Uncategorized | Posted on 14-06-2009

0

Last week, I created a simple online tool for minifying Javascript snippets or entire Javascript files.

Javascript

Check it out

JSMinifier.com

Kaltura Wordpress Plugin – Switching Partner IDs

Posted by Jason | Posted in mysql, php | Posted on 26-05-2009

0

I am using the Kaltura All-In-One-Video Wordpress Plugin on a project these days and I’ve come across a situation where I needed to switch my Partner ID to a new one (we purchased a paid account).

However, there is currently no way of doing this in the interface or by editing any of the plugin files… weird.

After calling their support and getting no answer, I found my own solution and I’m posting it here in hopes that it may help you.

This involves deleting a few rows from the wordpress database, so I’d recommend doing a backup before any of this.

Simply running the following SQL statement on your wordpress database will remove all Kaltura configurations:

delete from wp_options WHERE option_name LIKE ‘kaltura%’;

After running this statement, login to the admin area of Wordpress and you will now be prompted to Create a Partner ID (or specify an existing one).

Hope this helps!

Blueprint CSS Framework

Posted by Jason | Posted in css, html | Posted on 30-04-2009

1

The past few projects I’ve worked on, I’ve opted to use the Blueprint CSS Framework.

Blueprint offers several things that truly make a developer happy:

  1. Small footprint
  2. Instant cross-browser compatibility
  3. Simple grid-based framework that allows for the creation of simple to complex web designs
  4. The grid is completely customizable.
  5. Did I mention cross-browser compatibility?

I’ve always considered myself fairly fluent with CSS, but nothing is more frustrating than wasting a few hours getting things to line up properly in all browsers when you could be spending that time making the product more stable or adding new features.

Blueprint CSS uses a CSS Reset style, and then sets very nice (yet configurable) defaults for fonts, font sizes, alignment, grid, etc. For those who aren’t aware, a CSS Reset style is essentially a few lines of cleverly crafted CSS that removes the default options browsers set for things like font sizes, alignment, and a variety of tag defaults. This dramatically improves ones ability to make a site cross-browser compatible, but requires that you manually set options you aren’t used to setting. Luckly Blueprint does this for you.

Ok, that’s enough support for Blueprint today. I’m not saying everyone should use it, but I’d highly recommend it. It saved me a ton of time and I’ve always been extremely happy with the results.

Books for dummies

Posted by Jason | Posted in rant | Posted on 14-04-2009

0

I was in a local book store today searching for a good iphone development book when I came across the most pathetic computer section I’ve ever seen.

Nearly every book is an [insert topic here] for dummies book.

MooFlow Firefox Uncaught Exception Fix

Posted by Jason | Posted in javascript | Posted on 23-03-2009

7

I am using MooFlow for a project at work and it is absolutely fantastic. Nothing else gives the ease of use and nice look like MooFlow. However, it kept throwing an uncaught exception in Firefox:

Error: uncaught exception: [Exception... "Component returned failure code: 0x80040111 (NS_ERROR_NOT_AVAILABLE) [nsIDOMCanvasRenderingContext2D.drawImage]” nsresult: “0×80040111 (NS_ERROR_NOT_AVAILABLE)” location: “JS frame :: http://your-server/MooFlow.js :: anonymous :: line 423″ data: no]

I have figured out a simple fix for this.

In the file MooFlow.js look for the following line of code:

ctx.drawImage(i, 0, 0, arg.width, arg.height);

And change it to this:

try {
ctx.drawImage(i, 0, 0, arg.width, arg.height);
} catch(err) {}

And that will do it!

Note: this “fix” will disable refllections in the firefox browser.

Slicehost CentOS RMagick Install

Posted by Jason | Posted in linux | Posted on 20-02-2009

1

I feel your pain.

The problem is that if you install ImageMagick and ImageMagick-devel from yum you end up with version 6.2.x instead of the required 6.3.x or higher that RMagick requires.

Just install from source.  Follow these steps.

wget ftp://ftp.imagemagick.org/pub/ImageMagick/ImageMagick.tar.gz

cd ImageMagick-6-??

./configure

make

make install

gem install rmagick

Relax with a beer.

Antipodr

Posted by Jason | Posted in php | Posted on 29-10-2008

5

Antipodr is a simple little tool I created with Jake Rutter that allows you to calculate the exact spot on the other side of the planet from any location you enter.  A complete waste of time, yes, but fun!

Antipodr utilizes Google Maps and the Google Geocoding Web Service to bring you the end result.  Once the system determines the coordinates, a simple calculation determines the antipodal point (hence the domain name) and displays the map of that area.

On a side note, it turns out you’d have to live in Chile or Argentina in order to dig to China.  Lies!

Antipodr - Find the other side of the world!

Antipodr - Find the other side of the world!

Check out Antipodr now!