Index: templates/macros.cs
===================================================================
--- templates/macros.cs	(revision 5827)
+++ templates/macros.cs	(working copy)
@@ -185,10 +190,13 @@
   /each ?></dl><?cs
  /if ?><?cs
  if:attach_href ?>
-  <form method="get" action="<?cs var:attach_href ?>"><div>
+  <form method="get" action="<?cs var:attach_href ?>" style="display:inline;">
    <input type="hidden" name="action" value="new" />
    <input type="submit" value="Attach File" />
-  </div></form><?cs
+  </form>  <form method="get" action="<?cs var:attach_href ?>" style="display:inline;">
+   <input type="hidden" name="action" value="getzip" />
+   <input type="submit" value="Save all as ZIP-file" />
+  </form><?cs
  /if ?><?cs if:len(attachments) ?></div><?cs /if ?><?cs
 /def ?><?cs
 
Index: trac/attachment.py
===================================================================
--- trac/attachment.py	(revision 5827)
+++ trac/attachment.py	(working copy)
@@ -21,6 +21,8 @@
 import shutil
 import time
 import unicodedata
+import zipfile
+import tempfile
 
 from trac import perm, util
 from trac.config import BoolOption, IntOption
@@ -343,6 +345,13 @@
         action = req.args.get('action', 'view')
         if action == 'new':
             attachment = Attachment(self.env, parent_type, path)
+        elif action == 'getzip':
+            segments = path.split('/')
+            parent_id = '/'.join(segments[:-1])
+            last_segment = segments[-1]
+            if len(segments) == 1:    
+                self._do_getzip(req, parent_type, last_segment)
+                return 'attachment.cs', None
         else:
             segments = path.split('/')
             parent_id = '/'.join(segments[:-1])
@@ -434,6 +443,25 @@
 
     # Internal methods
 
+    def _do_getzip(self, req, p_type, p_id):
+        db = self.env.get_db_cnx()
+
+        zfname = 'Ticket%s.zip' % p_id
+
+        zfpath = os.path.join(tempfile.gettempdir(), zfname)
+
+        zf = zipfile.ZipFile(zfpath, 'w')
+        for attachment in Attachment.select(self.env, p_type, p_id, db):
+            zf.write(attachment.path, attachment.filename.encode('ascii'))
+        zf.close()
+
+        req.send_header('Content-Disposition', 'attachment; filename=%s' % zfname)
+        mime_type = 'application/octet-stream'
+        
+        req.send_file(zfpath, mime_type)
+        
+        os.remove(zfpath)
+
     def _do_save(self, req, attachment):
         perm_map = {'ticket': 'TICKET_APPEND', 'wiki': 'WIKI_MODIFY'}
         req.perm.assert_permission(perm_map[attachment.parent_type])

