When sending a file via UUID Services, e.g. using the deploy module, if there is already a file with the same URI present on the receiving system, but a different UUID, then an exception will be thrown like: "PDOException: SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '' for key 'uri': INSERT INTO {file_managed}...". Additionally an error like: "Warning: Header may not contain more than a single header, new line detected in drupal_send_headers()" may also appear, which is due to the services module tacking the exception message onto the HTTP status header.

This is happening because UUID Services is only checking for files with a matching UUID and does not check for URI conflicts before it saves the file.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

gilgabar’s picture

Status: Active » Needs review
FileSize
2.28 KB

The attached patch should resolve the issue. It handles the saving of file entities more carefully, checking for a file with a conflicting URI, and renaming the new file when that is the case. It also handles the case which follows from this when you attempt to send the same file a second, third, etc time, so that it will match on the UUID and use the same renamed file rather than creating additional renamed copies for each subsequent request.

kenorb’s picture

jamesmorrish’s picture

hmmmm me neither..

David_Rothstein’s picture

Issue summary: View changes
FileSize
2.65 KB
910 bytes

The previous patch has a problem when the file is something like a video (for example, as managed by the Media YouTube module).

It's actually an existing problem with the code but the patch makes it worse:

      $directory = drupal_dirname($uri);
       file_prepare_directory($directory, FILE_CREATE_DIRECTORY);
-      file_unmanaged_save_data(base64_decode($entity->file_contents), $entity->uri, FILE_EXISTS_REPLACE);
+      $entity->uri = file_unmanaged_save_data(base64_decode($entity->file_contents), $uri, $replace);

Trying to get a local directory name from a URI like "youtube://whatever" doesn't make sense and will fail. By writing the failed result back into $entity->uri that winds up empty and is later saved to the database, corrupting the data and prevented the video from being viewed at all with this patch applied.

Here's a new version of the patch which makes the code skip trying to write a local version of the file if the stream wrapper for the file indicates that it's not writable (like youtube://).

  • dixon_ committed 621db32 on 7.x-1.x
    Issue #1969222 by David_Rothstein, gilgabar: Fixed UUID Services:...
dixon_’s picture

Committed to 7.x-2.x, thanks a lot @gilgabar and @David_Rothstein!

dixon_’s picture

Status: Needs review » Fixed

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.