Save file to alternate location
December 4th, 2015
Common issue: the plugin saves files that are submitted via forms to the database…but I want to save the file to a special directory.
To do this, you create a filter as described on the page about Changing Form Data Before it is Saved but you use the following code.
Change the values of $formName, $fieldName and $uploaddir to suit your needs.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | function cfdbFilterSaveFile($formData) { // CHANGE THIS: CF7 form name you want to manipulate $formName = 'your-form'; // CHANGE THIS: upload field name on your form $fieldName = 'form-file'; // CHANGE THIS: directory where the file will be saved permanently $uploaddir = '/root/htdocs/wp-content/uploads/path/to/save/dir/'; if ($formData && $formName == $formData->title && isset($formData->uploaded_files[$fieldName])) { // make a copy of data from cf7 $formCopy = clone $formData; // breakdown parts of uploaded file, to get basename $path = pathinfo($formCopy->uploaded_files[$fieldName]); // directory of the new file $newfile = $uploaddir . $path['basename']; // check if a file with the same name exists in the directory if (file_exists($newfile)) { $dupname = true; $i = 2; while ($dupname) { $newpath = pathinfo($newfile); $newfile = $uploaddir . $newpath['filename'] . '-' . $i . '.' . $newpath['extension']; if (file_exists($newfile)) { $i++; } else { $dupname = false; } } } // make a copy of file to new directory copy($formCopy->uploaded_files[$fieldName], $newfile); // save the path to the copied file to the cfdb database $formCopy->posted_data[$fieldName] = $newfile; // delete the original file from $formCopy unset($formCopy->uploaded_files[$fieldName]); return $formCopy; } return $formData; } add_filter('cfdb_form_data', 'cfdbFilterSaveFile'); |
A More Sophisticated Example
Example where we save the file and add a URL to the file location into the form submission. Based on forum discussion.
This example is good if you have multiple forms to save file from. Here we have a reusable function “saveFilesInForm” and a “cfdbFilterSaveFiles” function that calls it. If you have multiple forms:
- create a new version of “cfdbFilterSaveFiles” with a unique function name for each form
- Add a new “add_filter” call for each form, passing the name of the new function
- The “saveFilesInForm” function appears only once
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | function cfdbFilterSaveFiles($formData) { // CHANGE THIS: CF7 form name you want to manipulate $formName = 'your-form'; if ($formData && $formName == $formData->title) { // CHANGE THIS: directory where the file will be saved permanently $uploadDir = '/root/htdocs/wp-content/uploads/path/to/save/dir/'; // CHANGE THIS: URL to the above directory $urlDir = 'http://your-site.com/uploads/path/to/save/dir/'; // CHANGE THIS: upload field names on your form $fieldNames = array('upload-field-1', 'upload-field-2', 'upload-field-3'); return saveFilesInForm($formData, $uploadDir, $urlDir, $fieldNames); } return $formData; } add_filter('cfdb_form_data', 'cfdbFilterSaveFiles'); function saveFilesInForm($formData, $uploadDir, $urlDir, $fieldNames) { // make a copy of data from cf7 $formCopy = clone $formData; foreach ($fieldNames as $fieldName) { if (isset($formData->uploaded_files[$fieldName])) { // breakdown parts of uploaded file, to get basename $path = pathinfo($formCopy->uploaded_files[$fieldName]); // directory of the new file $newfile = $uploadDir . $path['basename']; // check if a file with the same name exists in the directory if (file_exists($newfile)) { $dupname = true; $i = 2; while ($dupname) { $newpath = pathinfo($newfile); $newfile = $uploadDir . $newpath['filename'] . '-' . $i . '.' . $newpath['extension']; if (file_exists($newfile)) { $i++; } else { $dupname = false; } } } // make a copy of file to new directory copy($formCopy->uploaded_files[$fieldName], $newfile); // save the path to the copied file to the cfdb database $formCopy->posted_data[$fieldName] = $newfile; $path = pathinfo($newfile); $formCopy->posted_data[$fieldName . '-url'] = $urlDir . $path['basename']; // delete the original file from $formCopy unset($formCopy->uploaded_files[$fieldName]); } } return $formCopy; } |
Hi,
I tried using the code above replacing $formName and $uploaddir but it cannot seem to get files to upload into the directory. I’ve tried different variation on the directory path but nothing seems to work. The files are still posted to the database. Any suggestions would be greatly appreciated.
Cheers,
Brian
You might try setting up some debug statements in the code to see what is going on. Look for the “Debug” section on this page.
Hi
I got this part working, but having troubles showing the records in the admin.
In the tables of the admin it links only the files stored in the db for download.
Is there any config or easy way to show download links in the admin for files stored in the filesystem as well?
Cheers, Sebi
In the code above, I would set a new field to point to the uploaded file. After:
$formCopy->posted_data['form-file'] = $newfile;
I would add something like
$formCopy->posted_data['file-url'] = "http://your-site.com/path/to/$newfile";
Please remove above message, it was a mistake.
I am getting this message
PHP Warning: copy(): Filename cannot be empty in /html/wp-content/themes/xxx/functions.php on line 406
And the file is nowhere to be found.
Thanks in advance,
Shuki
I think the issue is you need to change ‘form-file’ to the name of the form field on your form. I’ll update that in the code example on this page.
Hello,
This snippet seems to not work in my situation also.
Some friendly observations using Contact Form 7:
-Email is sent out and it will be saved to the db, but on the front-end after submiting the sending proccess freezes (ajax-gif circles forever).
-File is not saved to the specified folder.
-In DB extension, attachment field shows the path of the file, but its not clickable and its not on ftp also.
Im running on WordPress 3.5.1, clean install, twentytwelve theme.
It would be really cool to get this snippet working somehowβ¦
Check if it is throwing an exception. Wrap all the code inside the function in a try-catch and print to your error log.
PS. Will need your php.ini file to have
error_log = /path/to/a/file/errors.txt
@Michael Simpson
Tried this, created the php.ini file and errors.txt file. errors.txt file is empty after I submit the form.
But I checked the WP error_log, and there was this line:
[07-May-2013 15:51:46 UTC] PHP Warning: copy(/public_html/wordpress/wp-content/uploads/pictures/Picture-1.png) [function.copy]: failed to open stream: No such file or directory in /home/rannoait/public_html/wordpress/wp-content/themes/twentytwelve/functions.php on line 488
Any help?
@r1987
Does /public_html/wordpress/wp-content/uploads/pictures/ exist and is it writeable?
@Michael Simpson
Yes, it exsists and its writable.
@r1987
If the copy line does not work, you could try this as an alterative and see if you get an error with more information
PS, be sure the directory is writeable by the user that the web server runs as (like “apache”).
Well, Michael. I have to appologize because of my dumbness.
What I did:
-I copied the path location from my FTP and it was /public_html/β¦
-I watched the error_log again now, and noticed, it showed /home/mydomainname/public_html/β¦
And I got the very first code working, it was the wrong path all the time.
Sorry for waisting your time. May-be it would be good to really make it red, that people some how copy the “real” root.
But there’s one more question that I have:
Lets say, that I have two forms with the upload field and I want both form uploads to go to the same folder, then I just copy/paste the same filter with just the new form name and field name right?
Regarding having two forms, I would try not to duplicate the code. Instead I would parameterize the function we have and create wrapper functions for each form submission. In other words, the following:
@Michael Simpson
Hi
Thanks for this, very good work, but not work with new WordPress properly. If i registering two filter work only first, and not to end. File be saved to disk and saved blob to db.
For me better work this:
when $script do:
Thanks anyway π
@korzex
Thanks for your comment. I suggest you add an “if” guarding “processing file” so that the function doesn’t try to save the file for other forms.
It is possible that two filters did not work when posting a submission to Form2 is because the first filter for Form1 had an error so the filter for Form2 did not run. I’m not sure about this.
Hi
Works very well π Thanks
Hi.
This example code works very well π
This example code will save the path to the copied file to the cfdb database,
but how if i want to save the url of the file that i uploaded to the database?
For example,
http://www.your-site.com/wordpress/wp-content/uploads/wpcf7_uploads/video.mp4
Thanks π
In addition to or instead of:
$formCopy->posted_data[$fieldName] = $newfile;
You could do something like:
$formCopy->posted_data['fileurl'] = 'http://.....';
@Michael Simpson
How if the file’s location and the file’s name being uploaded is also different?
For example:
http://www.your-site.com/wordpress/wp-content/uploads/wpcf7_uploads/video.mp4
http://www.your-site.com/wordpress/wp-content/uploads/wpcf7_uploads/video_1.mp4
http://www.your-site.com/wordpress/wp-content/uploads/wpcf7_uploads/TestingFile/video.mp4
Thanks π
@esyalaa
…then you must modify the code to make it behave as you wish.