RE: A Zip File Approach.
If a Zip file is OK and your happy to drive a solution via Visualforce page (client side processing). Then this Visualforce component library around the JSZip library will do what you want.
The demonstration on this blog shows unzipping and zipping (from attachments on a record) via an Office file (which is a zip file as it happens), using ZipFile custom object with attachments, however this the library itself is not bound to a specifc custom object, this is just an example one used in the blog.
NOTE: The resulting Zip file is sent back to VF page controller in the demo, however you could leave it on the client and use the JavaScript File IO libraries built into most browsers to save the file directly. Depending on the size of the resulting zip this will avoid any upload governors kicking in.
<c:zipfile name="someZipfile" state="{!ZipFile__c.Id}"
oncomplete="receiveZip(data);"
getzipfileentry=
"{!$RemoteAction.ZipDemoController.getZipFileEntry}">
<apex:repeat value="{!paths}" var="path">
<c:zipentry path="{!path}" base64="true"/>
</apex:repeat>
</c:zipfile>
@RemoteAction
public static String getZipFileEntry(String path, String state)
