Hi,
I'm in the process of converting the Avatar Selection module to Drupal 6.x. In it I want to use the file_save_upload() function but I'm having problems with the $dest parameter. The api documentation says:
file_save_upload($source, $validators = array(), $dest = FALSE, $replace = FILE_EXISTS_RENAME)
....
$dest A string containing the directory $source should be copied to. If this is not provided, the temporary directory will be used.
To me this sounds like I can set the $dest variable to be a path to a directory, so my code is :
$dest_dir = file_create_path('avatar_selection');
$validators = array(
'file_validate_is_image' => array(),
'file_validate_image_resolution' => array(variable_get('user_picture_dimensions', '85x85')),
'file_validate_size' => array(variable_get('user_picture_file_size', '30') * 1024),
);
$file = file_save_upload('picture_upload', $validators, $dest_dir, FILE_EXISTS_RENAME);
However, this gives me the following errors:
* warning: move_uploaded_file(files/travel-with-me.eu/avatar_selection) [function.move-uploaded-file]: failed to open stream: Is a directory in /var/www/drupal_6.1_20070904/html/includes/file.inc on line 570.
* warning: move_uploaded_file() [function.move-uploaded-file]: Unable to move '/tmp/phpcaqh3S' to 'files/travel-with-me.eu/avatar_selection' in /var/www/drupal_6.1_20070904/html/includes/file.inc on line 570.
* File upload error. Could not move uploaded file.
I think this is because the move_uploaded_file() expects its destination param to be the path to a file, not a directory. The file_save_upload() function doesn't modify the dest param if it's already set and so this function only works if (a) no destination param is provided or (b) if the destination provided is a file, not a directory.
Whichever way you look at it, this is a bug. Either the file_save_upload() function should be changed so it can update the destination to be a path to the file (based on supplied $dest) or the documentation should be updated so it correctly defines the $dest param.
Cheers,
Stella
| Comment | File | Size | Author |
|---|---|---|---|
| #18 | file_172943_1.patch | 3.13 KB | drewish |
| #14 | file_172943_0.patch | 1.01 KB | drewish |
| #13 | file_172943.patch | 0 bytes | drewish |
| #4 | file_save_upload_172943.patch | 3.08 KB | drewish |
Comments
Comment #1
drewish commentedgood point... i want to look around at how it's used before i want to weigh in on fixing the code or the docs.
Comment #2
stella commented+1 for changing the code
Look at the way it's implemented by user.module (user_validate_picture() func). It calls file_save_upload() without a destination param. This causes the file to be saved to e.g. "files/picture-1.gif". The user module then has to make another call, this time to file_copy() to copy the file to "files/pictures/". This results in there being two copies of the same file, one in the "files/" directory the other in "files/pictures/".
One of the comments at this section of code says "The image was saved using file_save_upload() and was added to the files table as a temporary file. We'll make a copy and let the garbage collector delete the original upload." Does the garbage collector really delete uploaded files from the files directory? How does it know that the file was copied to the "files/pictures/" directory? What if other modules just put their uploaded files in the "files/" directory and not in a subdirectory - will they get deleted? Maybe the user module should be using file_move() instead, but it seems like a needless step if file_save_upload() could save the file to where you want it in the first place.
Just my two cents.
Cheers,
Stella
Comment #3
drewish commentedi think it's best to provide a directory rather than a filename.
snpower, in the example you point of the user.module it wouldn't work providing a filename because you don't know the correct extension until you've had a chance to examine the file. so you don't know if it should be picture-1.gif or picture-1.jpg.
and to answer your question about the cron deletion, yes it does delete the temporary file because its path is saved in the database.
Comment #4
drewish commentedokay, this puts the PHPDoc comments in the right order and brings the code into line with them.
Comment #5
stella commentedI applied the patch to my system and used a call to file_save_upload() with the $dest param set to a directory and it worked perfectly.
Thanks!
Stella
Comment #6
drewish commentedcool well if we can get some more testing of the rest of core's uploads i think it'll be RTBC.
Comment #7
drewish commentedmarked http://drupal.org/node/176876 as a duplicate
Comment #8
drewish commentedchx, wanted me to bump this to critical
Comment #9
jakeg commentedAs per the duplicate of this thread, 'temporary files are not stored in temporary directory' due to this bug. I'd consider this a beta-2 blocker ( http://drupal.org/node/176876 )
Comment #10
drewish commentedjakeg, could you review this so we can get some RTBC action going?
Comment #11
drewish commentedI hate RTBCing my own patch but since the bug came from one of patches.
Comment #12
gábor hojtsyI did no test the patch yet, but the comment is still not in line with how it works. If you provide a directory, but it is not writable, it falls back to the temp folder, which is not documented.
I think this needs some testing with the core upload forms.
Comment #13
drewish commentedGábor, this fixes the documentation. what sort of testing did you have in mind?
Comment #14
drewish commentedhumm, that didn't seem to work.
Comment #17
dries commenteddrewish: can you create one patch instead of two patches?
Comment #18
drewish commentedwhoops, sorry. i guess the first patch didn't apply before i made the change for the second. that's why you shouldn't patch in a hurry ;)
Comment #19
chx commentedDocs seem to be in order and functionality was tested in #5.
Comment #20
gábor hojtsyLooks good, thanks, committed.
Comment #21
(not verified) commentedAutomatically closed -- issue fixed for two weeks with no activity.