diff --git a/imagefield_zip.ahah.inc b/imagefield_zip.ahah.inc
index c11a88f..c2c9900 100644
--- a/imagefield_zip.ahah.inc
+++ b/imagefield_zip.ahah.inc
@@ -28,14 +28,14 @@ function imagefield_zip_js($type_name, $field_name) {
       $images = array_filter($extracted, '_imagefield_zip_is_archived_image');
     }
     else {
-      watchdog('imagefield_zip', 'Unpacked archive appears to be empty.', array(), 'warning');
+      watchdog('imagefield_zip', 'Unpacked archive appears to be empty.', array(), WATCHDOG_WARNING);
     }
 
     // Delete the zip file as we extracted and used everything we wanted from it.
     imagefield_zip_delete_file($file);
   }
   else {
-    watchdog('imagefield_zip', 'Failed to save uploaded file', array(), 'error');
+    watchdog('imagefield_zip', 'Failed to save uploaded file', array(), WATCHDOG_ERROR);
   }
 
   // Generate HTML for the images that where uploaded
@@ -249,14 +249,14 @@ function imagefield_zip_multigroup_js($type_name, $group_name) {
       $images = array_filter($extracted, '_imagefield_zip_is_archived_image');
     }
     else {
-      watchdog('imagefield_zip', 'Unpacked archive appears to be empty.', array(), 'warning');
+      watchdog('imagefield_zip', 'Unpacked archive appears to be empty.', array(), WATCHDOG_WARNING);
     }
 
     // Delete the zip file as we extracted and used everything we wanted from it.
     imagefield_zip_delete_file($file);
   }
   else {
-    watchdog('imagefield_zip', 'Failed to save uploaded file', array(), 'error');
+    watchdog('imagefield_zip', 'Failed to save uploaded file', array(), WATCHDOG_ERROR);
   }
 
   // Generate HTML for the images that where uploaded
diff --git a/imagefield_zip.module b/imagefield_zip.module
index 3709258..a360ccc 100644
--- a/imagefield_zip.module
+++ b/imagefield_zip.module
@@ -308,41 +308,99 @@ function _imagefield_zip_fields(&$type) {
  */
 function imagefield_zip_extract($filepath) {
   $extracted = array();
+  // Exit if zip_open function does not exist.
   if (!function_exists('zip_open')) {
-    watchdog('imagefield_zip', 'Required function zip_open was not available', array(), 'error');
+    watchdog('imagefield_zip', 'Required function zip_open was not available', array(), WATCHDOG_CRITICAL);
     return NULL;
   }
-  if ($z = zip_open($filepath)) {
-    $dest = file_destination(file_directory_temp() .'/'. basename($filepath, '.zip'), FILE_EXISTS_RENAME);
-    mkdir($dest, 0755);
-
-    while ($entry = zip_read($z)) {
-      if (zip_entry_open($z, $entry, 'r') && ($zip_entry_filesize = zip_entry_filesize($entry))) {
-        $entry_name = zip_entry_name($entry);
-        $data = zip_entry_read($entry, $zip_entry_filesize);
-
-        $filepath = $dest .'/'. $entry_name;
-        $parent_dir = dirname($filepath);
-        if (!file_exists($parent_dir)) {
-          mkdir($parent_dir, 0777, TRUE);
-        }
 
-        if ($filepath = file_save_data($data, $filepath)) {
-          $file = new stdClass();
-          $file->filepath = $filepath;
-          $file->filename = $entry_name;
-          $file->filemime = file_get_mimetype($filepath);
-          $file->filesize = filesize($filepath);
-          $extracted[] = $file;
-        }
-        zip_entry_close($entry);
-      }
+  // Open zip file.
+  $z = zip_open($filepath);
+  $max_filesize = parse_size(file_upload_max_size());
+
+  // Exit if unable to open zip file.
+  if (!is_resource($z)) {
+    watchdog('imagefield_zip', 'Failed to unpack uploaded file %filepath. %error', array(
+      '%filepath' => $filepath,
+      '%error' => imagefield_zip_error($z),
+    ), WATCHDOG_WARNING);
+    return $extracted;
+  }
+
+  // Create directory if it doesn't exist.
+  $dest = file_destination(file_directory_temp() .'/'. basename($filepath, '.zip'), FILE_EXISTS_RENAME);
+  mkdir($dest, 0755);
+
+  // Itterate over each file.
+  while ($entry = zip_read($z)) {
+    if (!zip_entry_open($z, $entry, 'r')) {
+      watchdog('imagefield_zip', 'Failed to read an entry in the uploaded file %filepath. %error', array(
+        '%filepath' => $filepath,
+        '%error' => imagefield_zip_error($entry),
+      ), WATCHDOG_WARNING);
+      continue;
     }
 
-    zip_close($z);
+    // Get the file's size and name.
+    $filesize = zip_entry_filesize($entry);
+    $entry_name = zip_entry_name($entry);
+
+    // Make sure filesize is within limits.
+    if (empty($filesize) || $filesize > $max_filesize) {
+      watchdog('imagefield_zip', 'Zip file %filepath containing %entry is either empty or over the max file size: %size', array(
+        '%filepath' => $filepath,
+        '%entry' => $entry_name,
+        '%size' => format_size($max_filesize),
+      ), WATCHDOG_WARNING);
+      continue;
+    }
+
+    // Create destination directory if it doesn't exist.
+    $file_dest = $dest . '/' . $entry_name;
+    $parent_dir = dirname($file_dest);
+    if (!file_exists($parent_dir)) {
+      mkdir($parent_dir, 0777, TRUE);
+    }
+
+    // Create temp target file.
+    $file_source = file_directory_temp();
+    // On Windows, tempnam() requires an absolute path, so we use realpath().
+    $file_source = tempnam(realpath($file_source), 'file');
+    if (!$fp = fopen($file_source, 'wb')) {
+      drupal_set_message(t('The file could not be created %name.', array('%name' => $file_source)), 'error');
+      continue;
+    }
+
+    // Read/Write up to 1MB per step. Prevents excessive memory usage.
+    while ($filesize > 0) {
+      $readsize = min($filesize, 1048576);
+      // Decrease the size of the remaining data to read.
+      $filesize -= $readsize;
+
+      // Get the data.
+      $content = zip_entry_read($entry, $readsize);
+      // Write the data (if any).
+      if ($content !== FALSE) {
+        fwrite($fp, $content);
+      }
+    }
+    fclose($fp);
+
+    // Move file and create file object.
+    if (file_move($file_source, $file_dest)) {
+      $file = new stdClass();
+      $file->filepath = $file_source;
+      $file->filename = $entry_name;
+      $file->filemime = file_get_mimetype($file_source);
+      $file->filesize = filesize($file_source);
+      $extracted[] = $file;
+    }
+    zip_entry_close($entry);
   }
-  else {
-    watchdog('imagefield_zip', 'Failed to unpack uploaded file %filepath', array('%filepath' => $filepath), 'error');
+  zip_close($z);
+  // Free memory.
+  if (isset($content)) {
+    unset($content);
   }
 
   return $extracted;
@@ -356,7 +414,7 @@ function imagefield_zip_extract($filepath) {
  */
 function imagefield_zip_delete_file(&$file) {
   if (empty($file)) {
-    watchdog('imagefield_zip', 'Attempted to delete a non-existent file. Failing', array(), 'error');
+    watchdog('imagefield_zip', 'Attempted to delete a non-existent file. Failing', array(), WATCHDOG_NOTICE);
     return NULL;
   }
   if ($file->fid) {
@@ -374,7 +432,7 @@ function imagefield_zip_delete_file(&$file) {
 function imagefield_zip_is_valid_zip(&$file) {
   $errors = array();
   if (!function_exists('zip_open')) {
-    watchdog('imagefield_zip', 'Required function zip_open was not available', array(), 'error');
+    watchdog('imagefield_zip', 'Required function zip_open was not available', array(), WATCHDOG_CRITICAL);
     $errors[] = t('Required function zip_open was not available');
     return $errors;
   }
@@ -383,7 +441,7 @@ function imagefield_zip_is_valid_zip(&$file) {
   }
   else {
     $errors[] = t('The file is not a valid zip file or may be corrupt.');
-    watchdog('imagefield_zip', 'Invalid zip file %file', array('%file' => $file), 'error');
+    watchdog('imagefield_zip', 'Invalid zip file %file', array('%file' => $file), WATCHDOG_ERROR);
   }
   return $errors;
 }
@@ -406,3 +464,47 @@ function _imagefield_zip_is_archived_image(&$file) {
 
   return TRUE;
 }
+
+/**
+ * Report error from zip open function.
+ *
+ * @see http://php.net/manual/en/function.zip-open.php#75840
+ *
+ * @param $errno
+ *   Error number
+ */
+function imagefield_zip_error($errno) {
+  // using constant name as a string to make this function PHP4 compatible
+  $zipFileFunctionsErrors = array(
+    'ZIPARCHIVE::ER_MULTIDISK' => t('Multi-disk zip archives not supported.'),
+    'ZIPARCHIVE::ER_RENAME' => t('Renaming temporary file failed.'),
+    'ZIPARCHIVE::ER_CLOSE' => t('Closing zip archive failed'),
+    'ZIPARCHIVE::ER_SEEK' => t('Seek error'),
+    'ZIPARCHIVE::ER_READ' => t('Read error'),
+    'ZIPARCHIVE::ER_WRITE' => t('Write error'),
+    'ZIPARCHIVE::ER_CRC' => t('CRC error'),
+    'ZIPARCHIVE::ER_ZIPCLOSED' => t('Containing zip archive was closed'),
+    'ZIPARCHIVE::ER_NOENT' => t('No such file.'),
+    'ZIPARCHIVE::ER_EXISTS' => t('File already exists'),
+    'ZIPARCHIVE::ER_OPEN' => t('Can\'t open file'),
+    'ZIPARCHIVE::ER_TMPOPEN' => t('Failure to create temporary file.'),
+    'ZIPARCHIVE::ER_ZLIB' => t('Zlib error'),
+    'ZIPARCHIVE::ER_MEMORY' => t('Memory allocation failure'),
+    'ZIPARCHIVE::ER_CHANGED' => t('Entry has been changed'),
+    'ZIPARCHIVE::ER_COMPNOTSUPP' => t('Compression method not supported.'),
+    'ZIPARCHIVE::ER_EOF' => t('Premature EOF'),
+    'ZIPARCHIVE::ER_INVAL' => t('Invalid argument'),
+    'ZIPARCHIVE::ER_NOZIP' => t('Not a zip archive'),
+    'ZIPARCHIVE::ER_INTERNAL' => t('Internal error'),
+    'ZIPARCHIVE::ER_INCONS' => t('Zip archive inconsistent'),
+    'ZIPARCHIVE::ER_REMOVE' => t('Can\'t remove file'),
+    'ZIPARCHIVE::ER_DELETED' => t('Entry has been deleted'),
+  );
+  $errmsg = 'unknown';
+  foreach ($zipFileFunctionsErrors as $constName => $errorMessage) {
+    if (defined($constName) && constant($constName) === $errno) {
+      return 'Zip File Function error: ' . $errorMessage;
+    }
+  }
+  return 'Zip File Function error: unknown ' . $errno;
+}
