Here's what worked for me (and works VERY well):
Using the script linked from zend.com (above), I am able to dynamically assemble the zip and stream it immediately to the client, so there is no longer even a need to keep track of any files written to disk.
For large files, you have to make sure you set php.ini's max memory usage settings appropriately.
Forcing the download was a little tricky, though. Netscape/Win has a little bug that does not append the corrent file extension when the zip is assembled dynamically, so you have to warn the user. Other than that, it works perfectly in all other browsers, including Mac browsers.
Use the following headers:
header('Pragma: public');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Content-Type: application/zip'); // <- this could be octet-stream, as well
header('Content-Disposition: attachment; filename='.$filename.';');
header('Content-Transfer-Encoding: binary');
Hope that's of some use to you all. Thanks for all the great feedback.
Steve