Index: modules/system/system.api.php
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.api.php,v
retrieving revision 1.5
diff -u -r1.5 system.api.php
--- modules/system/system.api.php	20 Dec 2008 18:24:40 -0000	1.5
+++ modules/system/system.api.php	23 Dec 2008 20:53:15 -0000
@@ -1184,6 +1184,24 @@
 }
 
 /**
+ * Respond to a file that has been transferred.
+ *
+ * This hook is called when a file has been fully transferred.
+ *
+ * @param $source
+ *   String specifying the file path to transfer.
+ * @param $headers
+ *   An array of HTTP headers to send along with file.
+ *
+ * @return
+ *   None.
+ *
+ * @see file_transfer()
+ */
+function hook_file_transferred($source, $headers) {
+}
+
+/**
  * Check installation requirements and do status reporting.
  *
  * This hook has two closely related uses, determined by the $phase argument:
Index: includes/file.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/file.inc,v
retrieving revision 1.146
diff -u -r1.146 file.inc
--- includes/file.inc	4 Dec 2008 11:09:33 -0000	1.146
+++ includes/file.inc	23 Dec 2008 20:53:14 -0000
@@ -1197,14 +1197,15 @@
     drupal_set_header($header);
   }
 
-  $source = file_create_path($source);
-
   // Transfer file in 1024 byte chunks to save memory usage.
-  if ($fd = fopen($source, 'rb')) {
+  if ($fd = fopen(file_create_path($source), 'rb')) {
     while (!feof($fd)) {
       print fread($fd, 1024);
     }
     fclose($fd);
+
+    // Notify other modules that the file has been fully transferred.
+    module_invoke_all('file_transferred', $source, $headers);
   }
   else {
     drupal_not_found();
