The sugar configuration option for upload_wrapper_class
$sugar_config['upload_wrapper_class'] (See: Angel Magana's Angel's Blog: SugarCRM Customization: Custom Upload Directories )
allows developers to extend the UploadStream class defined in upload_file.php thus allowing the manipulation of Upload directory structures.
With over 600K files in our upload directory it is becoming increasingly important for us to be able to split the uploads directory into subdirs for the file system to be able to operate properly.
When uploading a file in a module, for example in Notes, a temporary file is created, the bean is saved, then the temp file is moved to its permanent location with the ID of the corresponding bean. This final move is done by the clients/base/api/ModuleApi.php function "moveTemporaryFiles"
This function uses UploadStream to retrieve the temporary file:
$basepath = UploadStream::path('upload://tmp/');
but not to determine the destination which is defined as:
$destination = rtrim($configDir, '/\\') . '/' . $filename;
$configDir = SugarConfig::getInstance()->get('upload_dir', 'upload');
Which means the permanent file is always placed in uploads/. regardless of any extensions made to UploadStream to define subdirectories.
A simple change to:
$configDir = UploadStream::getFSPath(SugarConfig::getInstance()->get('upload_dir', 'upload'));
solves this problem.
I would like to suggest that any and all manipulation of file uploads go through the UploadFile / UploadStream classes defined in upload_file.php.