to the first person that can help me.

On my site, every user has a subdirectory within the 'files' directory ('files' is what I have it configured to, set in admin->settings). I want uploads to go to this folder. I need to edit file.inc (or possibly upload.module - I'm not sure.) to make this happen. Where is the code that determines the final resting place of the uploaded file?

I say "final resting place" because I believe the file is uploaded to a temp directory and then moved.

THANK YOU!

Comments

tesla.nicoli’s picture

jeepfreak’s picture

I'm guessing you mean the

$dest = file_create_path($dest);
$directory = $dest;
$basename = file_check_path($directory);

part specifically? Redefining $dest or $directory doesn't seem to be working.

Malthus’s picture

File saving is done by the function file_save_upload() in includes/file.inc. This function is called by the upload module in upload_save() and in upload_nodeapi.

You would need to modify these calls to be something like

global $user;
file_save_upload($file, $user->name.'/'.$file->filename);

I hope you know what you are doing :)

jeepfreak’s picture

AWESOME!! THANK YOU!!
What's your paypal address? =)

tostinni’s picture

I got an "File copy failed: no directory configured, or it could not be accessed." error...

I don't understand why drupal fails at creation of the new directory...

I would also recommend you no to use name, because it may change (users are allowed to do this)...

jeepfreak’s picture

Yeah, it works. I'm actually using UID, not username, and I have added code to upload.module so that it creates the directory if it's not already there. I could post the code here if ya want.

tostinni’s picture

Btw, why a unique file directory ?
Do you plan to add something like a filebrowser per user ?

jeepfreak’s picture

I just don't want to have a billion files all in one folder. I may add functionality for a user to browse their files, but is doesn't have anything to do with the directory structure. For that I added a spot in 'files' table for UID.

Anyway... I added this around line 200 in upload.module

//Checks to see if there is an upload directory for the specific user.
//If there isn't it creates one at within your configured 'files' directory.
$uploadpath = variable_get('file_directory_path', 'files');
$directory_path = $uploadpath."/".$node->uid;
file_check_directory($directory_path, FILE_CREATE_DIRECTORY, 'file_directory_path');

Then I modified this line (near 379 in upload.module):

//prints the img tag, makes it red, and changes the url to reflect the user's specific upload directory
$file->filename ."<br /><font color=red><small>&lt;img src=&quot;". file_create_url(($file->fid ? $file->filepath : file_create_filename($node->uid ."/". $file->filename, file_create_path()))) ."&quot;&gt;</font></small>", 

Next, I changed this around line 342:

file_save_upload($file, $file->filename)

to this:

file_save_upload($file, $node->uid .'/'. $file->filename)

And finally, I changed this around line 256:

url(file_create_filename($file->filename, file_create_path()))))

to this:
url(file_create_filename($node->uid ."/". $file->filename, file_create_path()))))

Hope this helps!
Billy

jeepfreak’s picture

I could just send you my upload.module if you want too ;)

jeepfreak’s picture

OK, it looks like my last obstical is figuring out why the uploaded file is stored at www.example.com/files/upload.jpg when you are viewing the content preview and then gets moved to www.example.com/files/UID/upload.jpg when the content is submitted.

How do I get it to go to www.example.com/files/UID/ right off the bat?

Malthus’s picture

Did you edit both calls to file_save_upload? I believe the preview file saving action would be happening in upload_nodeapi:validate. There is a call to file_save_upload there as well.

Its not really a great idea to be hacking the core drupal files. It makes upgrading a pain (not to mention security patches). Ber Kessels is working on a betterupload module. Perhaps you want to take a look at that perhaps submit a patch for this functionality if you really find it to be useful.

Send any $$ to tyrius@hotmail.com :)

jeepfreak’s picture

I did try editing both, but the one in upload_nodeapi didn't seem to do anything (at least not what I'm looking for).

I understand what you're saying about editing core files and appreciate you pointing that out (since I hadn't thought about it.)

Thanks,
Billy

tesla.nicoli’s picture

I saw in the docs that you can use the hook_menu to start an event. To avoid changing the core I would create a module that changes the variable_get('file_directory_path', 'files'); and maybe if necessary variable_get('file_directory_temp', FILE_DIRECTORY_TEMP); contents.


function mymodule_menu(){

global $user:

variable_set('file_directory_path', 'files'.'/'.$user->uid);


}

Maybe hook_menu is not the right one but I could not find a bettr alternative. This is also better than hacking the code.

(not recommended:You could even add this code to the upload.module hook_menu as an alternative. A less complicated hack.)

jeepfreak’s picture

I'll play around with this, but I'm really just a beginner when it comes to this whole thing. I'm only decent when it comes to editing stuff, but starting from scratch is a ways away for me.
Thanks,
Billy

PS - Do you happen to have the link to where you read that about the menu hook? I'm wondering if there is an upload hook I could use instead?

tesla.nicoli’s picture

search http://www.drupaldocs.org. Don't worry the search there is much niceer than the search here ;)

jeepfreak’s picture

I found it now, and got it to work (as a new module even)! I can't believe that little line of code replaced all mine! The only problem I found with it, is it takes away your ability to set the "File system path" in Admin->settings. This I can deal with, but... any work arounds?
Thanks,
Billy

jeepfreak’s picture

OMG! Check this out...

function mymodule_menu(){
global $user;
$upload_dir = variable_get('upload_dir', 'files');
variable_set('file_directory_path', $upload_dir.'/'.$user->uid);
}

function mymodule_settings() {
$output = form_textfield(t('File Directory'), 'upload_dir',
variable_get('upload_dir', 'files'), 60, 60,
t('Where should we put the user\'s upload directories?')); 
return $output;
}
tesla.nicoli’s picture

Heehee you sound like I did when I got my first java timer to work :)

jeepfreak’s picture

damn, the setting page didn't work as well as I had thought.

tesla.nicoli’s picture

I thought you might ask. I could not figure the logical checks without asking you if the admins are supposed to have seperate directories also. If they are then do a check based on the URL. If not then do a check based on user access. You will have to make some decisions on what is important when checking. But here are some examples of what you can check for

function mymodule_menu(){
global $user:

if (!user_access('access administration pages') || !user_access('administer site configuration') || !user_access('bypass input data check')){
variable_set('file_directory_path', 'files'.'/'.$user->uid);
}
else
{
variable_set('file_directory_path', 'files');
}

}

or

function mymodule_menu(){
global $user:

if (arg(0) != 'admin'){
variable_set('file_directory_path', 'files'.'/'.$user->uid);
}
else
{
variable_set('file_directory_path', 'files');
}

}

You might have to play with this a bit and check the documentation other ways to set conditions.

jeepfreak’s picture

Yes, I did plan on having admins have seperate directories (there's only 1 admin anyway). The two examples are both to check permissions, correct? Not URL?
Thanks,
Billy

tesla.nicoli’s picture

The second example checks the URL for when you are in the administration section. So even the admins will get a directory.

You can still use your settings code I think. If you want to change the 'files' default and avoid a infinate loop.

jeepfreak’s picture

I keep getting this error:

warning: Cannot modify header information - headers already sent by (output started at /home/site/public_html/drupal/modules/mymodule.module:12) in /home/site/public_html/drupal/includes/common.inc on line 192.

But I'm gonna stick to calling the folder "files" anyway, so it's not really a problem.

Thanks,
Billy

venkat-rk’s picture

Don't know anything of php, but the few times I had this during my first drupal installs, it was because of extra space at the bottom of the php file.

tostinni’s picture

That's why ?> was removed from all modules in core.
See http://drupal.org/node/29385

jeepfreak’s picture

It wouldn't have been possible to skip all this and enter something like:
'files'.'/'.$user->uid directly into the File system path field at Admin->settings, right? That would be too simple =)

tesla.nicoli’s picture

lol

then you would have to hack it again because to get the string to be php code you would have to get an eval() in the upload code somewhere.

There are things you can add to make this lots better. I am a bit short on time though and trying to read and not code so much in the time I have over. Otherwise I would jump in because it is an intersting thing you are doing.

jeepfreak’s picture

Yeah, just checking. Thank you for your help so far! I have learned a lot!

venkat-rk’s picture

Just wondering...the working module you have is able to do all this without hacking into core?

jeepfreak’s picture

Damn, I hate to bring this thread back, but I found a problem. Apparently the avatar/user pics are stored in a subdirectory of the system files directory... this leads to this
error:files/3/files/2/picture-2.gif not found.

What's the easiest way to tell it not to use the 'files' directory and just use the 'drupal/avatar' directory for everyone?

Thanks again,
Billy

tesla.nicoli’s picture

Hmm,

I have never worked with the avatars. Are they part of a contributed module or a default Drupal setting?

jeepfreak’s picture

They seem to be a Drupal default setting. You can configure where you want them stored through Admin->Users->Config, but whatever you put there is created within your 'files' directory (or in my case, my files/$user->uid directory)
Billy

tostinni’s picture

Not so easy as the user_validate_picture use file_save_upload and that you just modify it...
Can you give the error line where this appears ?
Because user picture make use of your file_upload_save modified function so maybe there's a problem there...

jeepfreak’s picture

Well, if I login with a regular user and upload an avatar/user pic though the profile->edit page, it seems to work fine... but then I logout and log in with a different user (or administrator) I don't see the other user's picture. Then if I go to the error log (within drupal), I see the error I posted above.

tostinni’s picture

Ok now, have a look at your DB and what's inside the column picture in user table ?
Then, have a look at your files directory and locate the realpath.

Then you have to modify your file_save_upload function because I think that your modification change the path to upload the file and this is not reflected in user.module when it saves the path for your image.

jeepfreak’s picture

Well, I screwed around with it and lost my place. I had entered something in the "user picture path" spot of Admin->users->config to get it to upload to the user's uploaded files directory (files/UID), and that's where the picture goes, but when a different user tries to call the picture up it tries to find it at files/3/files/2 (if user 2 was the one that uploaded it, and user 3 was trying to view it).
I'm supprised I'm not having the same problem with user attached files.
Billy

jeepfreak’s picture

Well, this is kinda weird... I de-activated my little module that modifies the files directory path and all the previously uploaded avatars show up. So, the stored path is an actual path? I'm lost.

tesla.nicoli’s picture

the variable is in the database so it may not be getting used by every module in the same way. Some of them may not call the hook_menu. You may have to check module by module or use something more global like hook_init

JordiTR’s picture

Thanks to all that helped to find that solution, it has helped me to solve some that issue on a module I've created.

My question, I hope the thread is not dead ;-), is that it has worked me for saving the files uploaded with the pages created with that module to a concret directory inside 'files/mydir/', but what is not working is the part to download inside 'files/mydir/nid/' being nid the id for the node. I've just added $node->nid to the path on the function but it doesn't create it if it doesn't already exists. The question is: how to force to create the directory if it doesn't exists? Any idea? Thanks in advance.