diff --git a/include/class.file.php b/include/class.file.php
index e4012bb4b9f7665438cc28fbc3818162f48579a7..b44f7af4542343ccd55e93c2db199e06ea343278 100644
--- a/include/class.file.php
+++ b/include/class.file.php
@@ -27,7 +27,8 @@ class AttachmentFile {
         if(!$id && !($id=$this->getId()))
             return false;
 
-        $sql='SELECT f.*, count(DISTINCT c.canned_id) as canned, count(DISTINCT t.ticket_id) as tickets '
+        $sql='SELECT id, type, size, name, hash, f.created, '
+            .' count(DISTINCT c.canned_id) as canned, count(DISTINCT t.ticket_id) as tickets '
             .' FROM '.FILE_TABLE.' f '
             .' LEFT JOIN '.CANNED_ATTACHMENT_TABLE.' c ON(c.file_id=f.id) '
             .' LEFT JOIN '.TICKET_ATTACHMENT_TABLE.' t ON(t.file_id=f.id) '
@@ -90,12 +91,24 @@ class AttachmentFile {
         return $this->ht['hash'];
     }
 
-    function getBinary() {
-        return $this->ht['filedata'];
+    function open() {
+        return new AttachmentChunkedData($this->id);
+    }
+
+    function sendData() {
+        $file = $this->open();
+        while ($chunk = $file->read())
+            echo $chunk;
     }
 
     function getData() {
-        return $this->getBinary();
+        # XXX: This is horrible, and is subject to php's memory
+        #      restrictions, etc. Don't use this function!
+        ob_start();
+        $this->sendData();
+        $data = &ob_get_contents();
+        ob_end_clean();
+        return $data;
     }
 
     function delete() {
@@ -110,7 +123,7 @@ class AttachmentFile {
 
         header('Content-Type: '.($this->getType()?$this->getType():'application/octet-stream'));
         header('Content-Length: '.$this->getSize());
-        echo $this->getData();
+        $this->sendData();
         exit();
     }
 
@@ -132,7 +145,7 @@ class AttachmentFile {
         
         header('Content-Transfer-Encoding: binary');
         header('Content-Length: '.$this->getSize());
-        echo $this->getBinary();
+        $this->sendData();
         exit();
     }
 
@@ -168,15 +181,9 @@ class AttachmentFile {
         if (!(db_query($sql) && ($id=db_insert_id())))
             return false;
 
-        foreach (str_split($file['data'], 1024*100) as $chunk) {
-            $sql='UPDATE '.FILE_TABLE
-                .' SET filedata = CONCAT(filedata,'.db_input($chunk).')'
-                .' WHERE id='.db_input($id);
-            if(!db_query($sql)) {
-                db_query('DELETE FROM '.FILE_TABLE.' WHERE id='.db_input($id).' LIMIT 1');
-                return false;
-            }
-        }
+        $data = new AttachmentChunkedData($id);
+        if (!$data->write($file['data']))
+            return false;
 
         return $id;
     }
@@ -213,44 +220,56 @@ class AttachmentFile {
                     .'SELECT file_id FROM '.FAQ_ATTACHMENT_TABLE
                 .') still_loved'
             .')');
+        AttachmentChunkedData::deleteOrphans();
         return db_affected_rows();
     }
 }
 
-class AttachmentList {
-    function AttachmentList($table, $key) {
-        $this->table = $table;
-        $this->key = $key;
+/**
+ * Attachments stored in the database are cut into 256kB chunks and stored
+ * in the FILE_CHUNK_TABLE to overcome the max_allowed_packet limitation of
+ * LOB fields in the MySQL database
+ */
+define('CHUNK_SIZE', 500*1024); # Beware if you change this...
+class AttachmentChunkedData {
+    function AttachmentChunkedData($file) {
+        $this->_file = $file;
+        $this->_pos = 0;
     }
 
-    function all() {
-        if (!isset($this->list)) {
-            $this->list = array();
-            $res=db_query('SELECT file_id FROM '.$this->table
-                .' WHERE '.$this->key);
-            while(list($id) = db_fetch_row($res)) {
-                $this->list[] = new AttachmentFile($id);
-            }
-        }
-        return $this->list;
+    function length() {
+        list($length) = db_fetch_row(db_query(
+             'SELECT SUM(LENGTH(filedata)) FROM '.FILE_CHUNK_TABLE
+            .' WHERE file_id='.db_input($this->_file)));
+        return $length;
     }
-    
-    function getCount() {
-        return count($this->all());
+
+    function read() {
+        # Read requested length of data from attachment chunks
+        list($buffer) = @db_fetch_row(db_query(
+            'SELECT filedata FROM '.FILE_CHUNK_TABLE.' WHERE file_id='
+            .db_input($this->_file).' AND chunk_id='.$this->_pos++));
+        return $buffer;
     }
 
-    function add($fileId) {
-        db_query(
-            'INSERT INTO '.$this->table
-                .' SET '.$this->key
-                .' file_id='.db_input($fileId));
+    function write($what, $chunk_size=CHUNK_SIZE) {
+        $offset=0;
+        for (;;) {
+            $block = substr($what, $offset, $chunk_size);
+            if (!$block) break;
+            if (!db_query('REPLACE INTO '.FILE_CHUNK_TABLE
+                    .' SET filedata=0x'.bin2hex($block).', file_id='
+                    .db_input($this->_file).', chunk_id='.db_input($this->_pos++)))
+                return false;
+            $offset += strlen($block);
+        }
+        return true;
     }
 
-    function remove($fileId) {
+    function deleteOrpans() {
         db_query(
-            'DELETE FROM '.$this->table
-                .' WHERE '.$this->key
-                .' AND file_id='.db_input($fileId));
+            'DELETE FROM '.FILE_CHUNK_TABLE.' WHERE file_id NOT IN '
+                .'( SELECT id FROM '.FILE_TABLE.') still_loved');
+        return db_affected_rows();
     }
 }
-?>
diff --git a/include/class.upgrader.php b/include/class.upgrader.php
index 7fa6c331ff542c44e7f4329c4e164f0848cf837e..2c898f646d7dd392790a55007774be1ae54c92a3 100644
--- a/include/class.upgrader.php
+++ b/include/class.upgrader.php
@@ -269,8 +269,6 @@ class Upgrader extends SetupWizard {
         $tasks=array();
         switch($phash) { //Add  patch specific scripted tasks.
             case 'c00511c7-7be60a84': //V1.6 ST- 1.7 * {{MD5('1.6 ST') -> c00511c7c1db65c0cfad04b4842afc57}}
-                $tasks[] = array('func' => 'migrateAttachments2DB',
-                                 'desc' => 'Migrating attachments to database, it might take a while depending on the number of files.');
                 $tasks[] = array('func' => 'migrateSessionFile2DB',
                                  'desc' => 'Transitioning to db-backed sessions');
                 break;
@@ -282,6 +280,10 @@ class Upgrader extends SetupWizard {
                 $tasks[] = array('func' => 'migrateGroupDeptAccess',
                                  'desc' => 'Migrating group\'s department access to a new table');
                 break;
+            case '15b30765-dd0022fb':
+                $tasks[] = array('func' => 'migrateAttachments2DB',
+                                 'desc' => 'Migrating attachments to database, it might take a while depending on the number of files.');
+                break;
         }
 
         //Check IF SQL cleanup exists. 
diff --git a/include/upgrader/sql/15b30765-dd0022fb.cleanup.sql b/include/upgrader/sql/15b30765-dd0022fb.cleanup.sql
new file mode 100644
index 0000000000000000000000000000000000000000..fdbd27d1f799d5da54b12d60522aa451f177798c
--- /dev/null
+++ b/include/upgrader/sql/15b30765-dd0022fb.cleanup.sql
@@ -0,0 +1,10 @@
+
+-- Drop fields we no longer need in the reference table.
+-- NOTE: This was moved from the 1.6* major upgrade script because the
+--       handling of attachments changed with dd0022fb
+ALTER TABLE `%TABLE_PREFIX%ticket_attachment`
+    DROP `file_size`,
+    DROP `file_name`,
+    DROP `file_key`,
+    DROP `updated`,
+    DROP `deleted`;
diff --git a/include/upgrader/sql/15b30765-dd0022fb.patch.sql b/include/upgrader/sql/15b30765-dd0022fb.patch.sql
new file mode 100644
index 0000000000000000000000000000000000000000..0006139d679fdf9af8924b639b488e3edc0f2c34
--- /dev/null
+++ b/include/upgrader/sql/15b30765-dd0022fb.patch.sql
@@ -0,0 +1,26 @@
+/**
+ * @version v1.7 RC2+
+ * @signature dd0022fb14892c0bb6a9700392df2de7
+ *
+ * Migrate file attachment data from %file to %file_chunk
+ *  
+ */
+
+DROP TABLE IF EXISTS `%TABLE_PREFIX%file_chunk`;
+CREATE TABLE `%TABLE_PREFIX%file_chunk` (
+    `file_id` int(11) NOT NULL,
+    `chunk_id` int(11) NOT NULL,
+    `filedata` longblob NOT NULL,
+    PRIMARY KEY (`file_id`, `chunk_id`)
+) ENGINE=MyISAM  DEFAULT CHARSET=utf8;
+
+INSERT INTO `%TABLE_PREFIX%file_chunk` (`file_id`, `chunk_id`, `filedata`)
+    SELECT `id`, 0, `filedata`
+    FROM `%TABLE_PREFIX%file`;
+
+ALTER TABLE `%TABLE_PREFIX%file` DROP COLUMN `filedata`;
+OPTIMIZE TABLE `%TABLE_PREFIX%file`;
+
+-- Finished with patch
+UPDATE `%TABLE_PREFIX%config`
+    SET `schema_signature`='dd0022fb14892c0bb6a9700392df2de7';
diff --git a/include/upgrader/sql/c00511c7-7be60a84.cleanup.sql b/include/upgrader/sql/c00511c7-7be60a84.cleanup.sql
index 01d69e2d72b732b2d7c3f618fd6e595ccb7c67f7..eabc72c9e22d724978f4f5449901ea5157b2b6a1 100644
--- a/include/upgrader/sql/c00511c7-7be60a84.cleanup.sql
+++ b/include/upgrader/sql/c00511c7-7be60a84.cleanup.sql
@@ -4,14 +4,6 @@ ALTER TABLE `%TABLE_PREFIX%config`
     DROP COLUMN `timezone_offset`,
     DROP COLUMN `api_passphrase`;
 
--- Drop fields we no longer need in the reference table.
-ALTER TABLE `%TABLE_PREFIX%ticket_attachment`
-    DROP `file_size`,
-    DROP `file_name`,
-    DROP `file_key`,
-    DROP `updated`,
-    DROP `isdeleted`;
-
 -- Drop fields we no longer need in staff table.
 ALTER TABLE `%TABLE_PREFIX%staff`
     DROP `append_signature`,
diff --git a/main.inc.php b/main.inc.php
index 8ce3946696c8bb959200e3ea2366805eff58efa5..235a6341a2db15e7be7b5c1e313e6b85e9b678f3 100644
--- a/main.inc.php
+++ b/main.inc.php
@@ -63,7 +63,7 @@
 
     #Current version && schema signature (Changes from version to version)
     define('THIS_VERSION','1.7-RC2+'); //Shown on admin panel
-    define('SCHEMA_SIGNATURE','15b3076533123ff617801d89861136c8'); //MD5 signature of the db schema. (used to trigger upgrades)
+    define('SCHEMA_SIGNATURE','dd0022fb14892c0bb6a9700392df2de7'); //MD5 signature of the db schema. (used to trigger upgrades)
     #load config info
     $configfile='';
     if(file_exists(ROOT_DIR.'ostconfig.php')) //Old installs prior to v 1.6 RC5
@@ -131,6 +131,7 @@
     define('SYSLOG_TABLE',TABLE_PREFIX.'syslog');
     define('SESSION_TABLE',TABLE_PREFIX.'session');
     define('FILE_TABLE',TABLE_PREFIX.'file');
+    define('FILE_CHUNK_TABLE',TABLE_PREFIX.'file_chunk');
 
     define('STAFF_TABLE',TABLE_PREFIX.'staff');
     define('DEPT_TABLE',TABLE_PREFIX.'department');
diff --git a/setup/inc/sql/osTicket-mysql.sql b/setup/inc/sql/osTicket-mysql.sql
index 6ac95bb523a74be12a537d09a5983e550e49e473..53e3c551999567641bd33c71b7056f45de546c6c 100644
--- a/setup/inc/sql/osTicket-mysql.sql
+++ b/setup/inc/sql/osTicket-mysql.sql
@@ -327,15 +327,24 @@ CREATE TABLE `%TABLE_PREFIX%file` (
   `size` varchar(25) NOT NULL default '',
   `hash` varchar(125) NOT NULL,
   `name` varchar(255) NOT NULL default '',
-  `filedata` longblob NOT NULL,
   `created` datetime NOT NULL,
   PRIMARY KEY  (`id`),
   KEY `hash` (`hash`)
 ) ENGINE=MyISAM  DEFAULT CHARSET=utf8;
 
-INSERT INTO `%TABLE_PREFIX%file` (`id`, `type`, `size`, `hash`, `name`, `filedata`, `created`) VALUES
-(1, 'text/plain', '25', '670c6cc1d1dfc97fad20e5470251b255', 'osTicket.txt', 0x43616e6e6564206174746163686d656e747320726f636b210a, NOW());
+INSERT INTO `%TABLE_PREFIX%file` (`id`, `type`, `size`, `hash`, `name`, `created`) VALUES
+(1, 'text/plain', '25', '670c6cc1d1dfc97fad20e5470251b255', 'osTicket.txt', NOW());
 
+DROP TABLE IF EXISTS `%TABLE_PREFIX%file_chunk`;
+CREATE TABLE `%TABLE_PREFIX%file_chunk` (
+    `file_id` int(11) NOT NULL,
+    `chunk_id` int(11) NOT NULL,
+    `filedata` longblob NOT NULL,
+    PRIMARY KEY (`file_id`, `chunk_id`)
+) ENGINE=MyISAM  DEFAULT CHARSET=utf8;
+
+INSERT INTO `%TABLE_PREFIX%file_chunk` (`file_id`, `chunk_id`, `filedata`)
+VALUES (1, 0, 0x43616e6e6564206174746163686d656e747320726f636b210a);
 
 DROP TABLE IF EXISTS `%TABLE_PREFIX%groups`;
 CREATE TABLE `%TABLE_PREFIX%groups` (
diff --git a/setup/inc/sql/osTicket-mysql.sql.md5 b/setup/inc/sql/osTicket-mysql.sql.md5
index 11c872a50b9a27b95388705d17ad0d7a43566ad1..e96b33654d6d528ac92f4613636491d6ffee3e0a 100644
--- a/setup/inc/sql/osTicket-mysql.sql.md5
+++ b/setup/inc/sql/osTicket-mysql.sql.md5
@@ -1 +1 @@
-15b3076533123ff617801d89861136c8
+dd0022fb14892c0bb6a9700392df2de7