June 12, 2020: Improved support for non-latin characters.
Jun 27, 2018: Updated to use
get_upload_dir()
method instead ofwp_upload_dir()
.November 19th, 2016: Fixed typo in method name.
October 24, 2016: Fixed issue with Gravity Forms 2.0.7. Major refactor. Requires Gravity Forms 2.0.7.15 or greater.
December 5, 2015: Added support for Post Image fields.
September 22, 2015: Updated to remove forward and backslashes from new filename.
March 26, 2015: Fixed issue when submitting form with no uploaded files
<?php | |
/** | |
* Gravity Wiz // Gravity Forms // Rename Uploaded Files | |
* | |
* Rename uploaded files for Gravity Forms. You can create a static naming template or using merge tags to base names on user input. | |
* | |
* Features: | |
* + supports single and multi-file upload fields | |
* + flexible naming template with support for static and dynamic values via GF merge tags | |
* | |
* Uses: | |
* + add a prefix or suffix to file uploads | |
* + include identifying submitted data in the file name like the user's first and last name | |
* | |
* @version 2.4 | |
* @author David Smith <david@gravitywiz.com> | |
* @license GPL-2.0+ | |
* @link http://gravitywiz.com/rename-uploaded-files-for-gravity-form/ | |
*/ | |
class GW_Rename_Uploaded_Files { | |
public function __construct( $args = array() ) { | |
// set our default arguments, parse against the provided arguments, and store for use throughout the class | |
$this->_args = wp_parse_args( $args, array( | |
'form_id' => false, | |
'field_id' => false, | |
'template' => '' | |
) ); | |
// do version check in the init to make sure if GF is going to be loaded, it is already loaded | |
add_action( 'init', array( $this, 'init' ) ); | |
} | |
public function init() { | |
// make sure we're running the required minimum version of Gravity Forms | |
if( ! is_callable( array( 'GFFormsModel', 'get_physical_file_path' ) ) ) { | |
return; | |
} | |
add_filter( 'gform_entry_post_save', array( $this, 'rename_uploaded_files' ), 9, 2 ); | |
add_filter( 'gform_entry_post_save', array( $this, 'stash_uploaded_files' ), 99, 2 ); | |
add_action( 'gform_after_update_entry', array( $this, 'rename_uploaded_files_after_update' ), 9, 2 ); | |
add_action( 'gform_after_update_entry', array( $this, 'stash_uploaded_files_after_update' ), 99, 2 ); | |
} | |
function rename_uploaded_files( $entry, $form ) { | |
if( ! $this->is_applicable_form( $form ) ) { | |
return $entry; | |
} | |
foreach( $form['fields'] as &$field ) { | |
if( ! $this->is_applicable_field( $field ) ) { | |
continue; | |
} | |
$uploaded_files = rgar( $entry, $field->id ); | |
if( empty( $uploaded_files ) ) { | |
continue; | |
} | |
$uploaded_files = $this->parse_files( $uploaded_files, $field ); | |
$stashed_files = $this->parse_files( gform_get_meta( $entry['id'], 'gprf_stashed_files' ), $field ); | |
$renamed_files = array(); | |
foreach( $uploaded_files as $_file ) { | |
// Don't rename the same files twice. | |
if( in_array( $_file, $stashed_files ) ) { | |
$renamed_files[] = $_file; | |
continue; | |
} | |
$dir = wp_upload_dir(); | |
$dir = $this->get_upload_dir( $form['id'] ); | |
$file = str_replace( $dir['url'], $dir['path'], $_file ); | |
if( ! file_exists( $file ) ) { | |
continue; | |
} | |
$renamed_file = $this->rename_file( $file, $entry ); | |
if ( ! is_dir( dirname( $renamed_file ) ) ) { | |
wp_mkdir_p( dirname( $renamed_file ) ); | |
} | |
$result = rename( $file, $renamed_file ); | |
$renamed_files[] = $this->get_url_by_path( $renamed_file, $form['id'] ); | |
} | |
// In cases where 3rd party add-ons offload the image to a remote location, no images can be renamed. | |
if( empty( $renamed_files ) ) { | |
continue; | |
} | |
if( $field->get_input_type() == 'post_image' ) { | |
$value = str_replace( $uploaded_files[0], $renamed_files[0], rgar( $entry, $field->id ) ); | |
} else if( $field->multipleFiles ) { | |
$value = json_encode( $renamed_files ); | |
} else { | |
$value = $renamed_files[0]; | |
} | |
GFAPI::update_entry_field( $entry['id'], $field->id, $value ); | |
$entry[ $field->id ] = $value; | |
} | |
return $entry; | |
} | |
function get_upload_dir( $form_id ) { | |
$dir = GFFormsModel::get_file_upload_path( $form_id, 'PLACEHOLDER' ); | |
$dir['path'] = dirname( $dir['path'] ); | |
$dir['url'] = dirname( $dir['url'] ); | |
return $dir; | |
} | |
function rename_uploaded_files_after_update( $form, $entry_id ) { | |
$entry = GFAPI::get_entry( $entry_id ); | |
$this->rename_uploaded_files( $entry, $form ); | |
} | |
/** | |
* Stash the "final" version of the files after other add-ons have had a chance to interact with them. | |
* | |
* @param $entry | |
* @param $form | |
*/ | |
function stash_uploaded_files( $entry, $form ) { | |
foreach ( $form['fields'] as &$field ) { | |
if ( ! $this->is_applicable_field( $field ) ) { | |
continue; | |
} | |
$uploaded_files = rgar( $entry, $field->id ); | |
gform_update_meta( $entry['id'], 'gprf_stashed_files', $uploaded_files ); | |
} | |
return $entry; | |
} | |
function stash_uploaded_files_after_update( $form, $entry_id ) { | |
$entry = GFAPI::get_entry( $entry_id ); | |
$this->stash_uploaded_files( $entry, $form ); | |
} | |
function rename_file( $file, $entry ) { | |
$new_file = $this->get_template_value( $this->_args['template'], $file, $entry ); | |
$new_file = $this->increment_file( $new_file ); | |
return $new_file; | |
} | |
function increment_file( $file ) { | |
$file_path = GFFormsModel::get_physical_file_path( $file ); | |
$pathinfo = pathinfo( $file_path ); | |
$counter = 1; | |
// increment the filename if it already exists (i.e. balloons.jpg, balloons1.jpg, balloons2.jpg) | |
while ( file_exists( $file_path ) ) { | |
$file_path = str_replace( ".{$pathinfo['extension']}", "{$counter}.{$pathinfo['extension']}", GFFormsModel::get_physical_file_path( $file ) ); | |
$counter++; | |
} | |
$file = str_replace( basename( $file ), basename( $file_path ), $file ); | |
return $file; | |
} | |
function is_path( $filename ) { | |
return strpos( $filename, '/' ) !== false; | |
} | |
function get_template_value( $template, $file, $entry ) { | |
$info = pathinfo( $file ); | |
if( strpos( $template, '/' ) === 0 ) { | |
$dir = wp_upload_dir(); | |
$template = $dir['basedir'] . $template; | |
} else { | |
$template = $info['dirname'] . '/' . $template; | |
} | |
// replace our custom "{filename}" psuedo-merge-tag | |
$value = str_replace( '{filename}', $info['filename'], $template ); | |
// replace merge tags | |
$form = GFAPI::get_form( $entry['form_id'] ); | |
$value = GFCommon::replace_variables( $value, $form, $entry, false, true, false, 'text' ); | |
// make sure filename is "clean" | |
$filename = $this->clean( basename( $value ) ); | |
$value = str_replace( basename( $value ), $filename, $value ); | |
// append our file ext | |
$value .= '.' . $info['extension']; | |
return $value; | |
} | |
function is_applicable_form( $form ) { | |
$form_id = isset( $form['id'] ) ? $form['id'] : $form; | |
return $form_id == $this->_args['form_id']; | |
} | |
function is_applicable_field( $field ) { | |
$is_file_upload_field = in_array( GFFormsModel::get_input_type( $field ), array( 'fileupload', 'post_image' ) ); | |
$is_applicable_field_id = $this->_args['field_id'] ? $field['id'] == $this->_args['field_id'] : true; | |
return $is_file_upload_field && $is_applicable_field_id; | |
} | |
function clean( $str ) { | |
return sanitize_file_name( $str ); | |
} | |
function get_url_by_path( $file, $form_id ) { | |
$dir = $this->get_upload_dir( $form_id ); | |
$url = str_replace( $dir['path'], $dir['url'], $file ); | |
return $url; | |
} | |
function parse_files( $files, $field ) { | |
if( empty( $files ) ) { | |
return array(); | |
} | |
if( $field->get_input_type() == 'post_image' ) { | |
$file_bits = explode( '|:|', $files ); | |
$files = array( $file_bits[0] ); | |
} else if( $field->multipleFiles ) { | |
$files = json_decode( $files ); | |
} else { | |
$files = array( $files ); | |
} | |
return $files; | |
} | |
} | |
# Configuration | |
new GW_Rename_Uploaded_Files( array( | |
'form_id' => 628, | |
'field_id' => 3, | |
'template' => '{Name (First):1.3}-{Name (Last):1.6}-{filename}' // most merge tags are supported, original file extension is preserved | |
) ); |
We wrote a snippet that will allow you to create a dynamic naming template for your uploaded Gravity Form files. This includes the ability to prepend, append or generate from scratch custom file names. You can use merge tags to include user input in your new file names.
Here are a couple use cases where this snippet might be useful:
- Include the name of the submitting user either before or after the file name.
- Include an event name in the file name to better categorize which files belong to which events.
For example, given an original file name of mountains.png and a template of {Name (First):1.3}-{Name (Last):1.6}-{filename}
, the final image name would be Jordan-Smith-mountains.png
Getting Started
- Check requirements
- Make sure you have Gravity Forms installed and activated.
- Already have a license? Download Latest Gravity Forms
- Need a license? Buy Gravity Forms
- Make sure you have Gravity Forms installed and activated.
- Install the snippet
- Copy and paste the entire snippet into your theme’s functions.php file.
- Configure the snippet
- Once you have installed the snippet, find the snippet configuration section located at the bottom of the snippet code.
- Replace the
form_id
with the ID of your form. - Replace the
field_id
with the field ID of your File Upload field. - Replace the
template
with your custom file name template.
Usage Examples
First and Last Name
new GW_Rename_Uploaded_Files( array( | |
'form_id' => 628, | |
'field_id' => 3, | |
'template' => '{Name (First):1.3}-{Name (Last):1.6}-{filename}' // most merge tags are supported, original file extension is preserved | |
) ); |
In this example, we are prepending the first and last name from the form to easily identify who submitted the file. Most merge tags are supported using this method and the original file extension is preserved.
Form Title Merge Tag
new GW_Rename_Uploaded_Files( array( | |
'form_id' => 12, | |
'field_id' => 18, | |
'template' => '{form_title}-{filename}' // most merge tags are supported, original file extension is preserved | |
) ); |
In this example, we are prepending the title of the form to the filename to quickly identify which form the file was uploaded to.
Static Text
new GW_Rename_Uploaded_Files( array( | |
'form_id' => 628, | |
'field_id' => 5, | |
'template' => 'static-file-name' | |
) ); |
You can use any text you’d like, just make sure to add the {filename}
merge tag somewhere in there.
Parameters
form_id (integer) (required)
Your Form ID. There is no default value.
field_id (integer) (required)
The Field ID of the file upload field. There is no default value.
template (string or merge tag) (required)
This is the template that controls how the file will be rewritten. The value can be either a static string or a merge-tag(s). There is no default value.
Was this helpful?
We hope you find this snippet useful! If you do, show us some love by sharing this article on the social media platform of your choice. Let’s keep the Gravity Wiz pumping out awesome snippets. Thanks!
Did this resource help you do something awesome with Gravity Forms? Then you'll absolutely love Gravity Perks; a suite of 32+ essential add-ons for Gravity Forms with support you can count on.
Hi Everyone,
I am trying to get the date to appear in the name of the my uploaded file, I tried using the merge tag of {Date:3}, {Date:3.1} (and .2 / .3) and {Date:3:value}, I am not wanting the date to appear as a date of 2/8/2021, but 2021-02-08 would be perfect, this way my client can see images in date order for example.
Any thoughts?
Thanks!
Ken
I forgot to add, I am getting the year with the Date:3 and Date:3:value merge tags.
Ken
Hi Ken,
The output format for a Date field’s merge tag is set by the Date Format option in the field settings. Change this to yyy-mm-dd and the file will be renamed accordingly.
Very useful code!
Is it possible to strip out special characters from the merge tags? I have a PHP function that does that, but can I insert PHP that calls a function inside your code snippet or will it break it?
BTW I got 3 gravity perks last week, the nested forms rock!
What you can do is extend our class with your own and then modify the clean function to do any kind of sanitization you want.
class Your_Rename_Uploaded_Files extends GW_Rename_Uploaded_Files { function clean( $str ) { return $str; } }
Thanks for this code – it’s been really useful!
I’ve been having an issue recently where a small number of files renamed using this snippet end up being saved as zero bytes in size.
There’s no obvious pattern to the affected files themselves, and in some cases the issue affects only a subset of files uploaded along with a single form submission.
I see no errors in the Apache or PHP logs that could shed light on the problem, and I haven’t been able to reproduce the problem myself. My best guess right now is that renaming is sometimes kicking in before the file uploads have finished, perhaps due to load on the server – is that a possibility?
If so, is there any way to ensure the uploads are definitely complete before renaming triggers? (Even just a way to ensure the original file isn’t lost would be helpful; I can’t find them in GF’s temporary upload folder.) And if not, can you think of any other explanations?
Thanks,
Hi Ben,
I haven’t experienced such before so I’m guessing this is an issue related to your server. You may want to check out our GP Media Library Perk, which enables the feature to automatically import uploaded files to the WordPress Media Library when the form is submitted. This can help ensure that you don’t lose any uploaded files in case you don’t find them in the GF Temporary upload folder.
Best,
can you use this with Slim Image Cropper?
Hello Alex, this is something that we would have to look into and see if we can work within the code. If you are a a Gravity Perks user, go ahead and leave us a message through our support page found here.
Hi,
When I’m pasting this snippet into my functions.php file I’m getting an error:
“There has been a critical error on your website. Please check your site admin email inbox for instructions.
Learn more about debugging in WordPress.”
how come? Do I need to change something more else than the bottom part?
Kind regards, Vincent
Hi Stephan,
It sounds like you might be having some trouble with installing the snippet. Please refer to our article on snippet troubleshooting for details on installing our snippets.
http://gravitywiz.com/documentation/snippet-troubleshooting/
However, if you’re a Gravity Perks Subscriber and you still experience issues installing the snippet, you can send us a message via our support form so we can take a closer look into it.
I hope this helps.
Best,
Hi Samuel,
Got it, thanks. And if you want to rename the file to a field other then the name? How could u achieve this?
Kind regards,
Hi Stephan,
Set the template parameter to the merge tag of the field you want to use its value to rename the file
'template' => '{:23}'
Best,
Like one of the replies above, I have multi site, so I cant add the code above to my functions as it will interfere with other GF’s. I tried using code snippet plugin but it throws an error. Do you have any other suggestion? On the functions file, Is there a way to check for site ID and then apply the code?
Hi Albert,
You can get the Current site/blog ID with this
get_current_blog_id();
, you can then put the snippet configuration inside an if statement to check if the current site id is equal to the ID of the site you want to target. Something like this should work for you.if (get_current_blog_id() == 4 ){ new GW_Rename_Uploaded_Files( array( 'form_id' => 628, 'field_id' => 3, 'template' => '{Name (First):1.3}-{Name (Last):1.6}-{filename}' ) ); }
I hope this helps.
Best,
Thanks for the clear instructions. It’s works on one image. In my form I have more than one image to be renamed. Do I need to use the whole code snippet each time for a new FieldID in the same form? Example Form ID is the same, Field ID changes, and naming works as your above instructions.
In fact, I’d like to use the snippet once and the rename instruction multiple times and for different forms. Is this possible? Then I just concentrate the renaming functionality in one place.
Thanks
Hi Stuart,
If you want to use the file rename snippet on more than one file upload field, you can create multiple copies of just the configuration. You don’t have to duplicate the entire snippet, but just the configuration part which will create multiple instances of the Class. Here is an article on how to apply a class-based snippet multiple times.
Best,
I have 4 file upload fields per form entry. Each of these 4 upload fields are multi upload.
I would want file name to be “Postage[EntryID]X” Where entry ID is the form entry ID and X is the upload number, so first upload is 1, then 2 etc.
How do I go about that (a bit confused because I have multi-upload and multiple fields? Thanks
Hi Chelsea,
You can use the
{entry_id}
merge tag to insert the entry ID into the renamed file, however numbering the files inside a multi-upload field isn’t currently supported.What you could do instead is use GF Nested Forms with a Single File upload field inside the Nested Form. You could then use the :count merge tag modifier in a field in the Nested Form to count the number of uploaded files, as shown in this article.
I have a WP Multisite set up with http://www.mainsite.com/subsite/... format. I have plugins for Gravity Forms and Wp DataTables with Gravity Forms integration. I also have the Gravity Perks installed. My sub-sites are designed for separate use/access by separate clients. The sub-sites each have a number of Gravity Forms that are ‘checklists’ collecting info on different things. A number of the forms are checklists for reviewing documents and they have a file upload field to enable the client to upload a pdf copy of the document that they reviewed.
Can this snippet be applied to work on a Multi-site set up for a number of different forms each with a file upload field?
On each form I use the GF Perks Unique ID to create a unique sequential number for each submitted form. Is it possible for the upload file to be include this in the new file name?
For example a file to be renamed as “XX00123Company Name” where XX00123 is the Unique ID sequential number and Company Name is the value input for a given company name field in the form.
As I say I will have another separate form for, say, a legal document checklist with another Unique ID, say. “LG001” and, say, a document title name field, say, “Trust Deed” that I would want the file upload to be saves as “LG001_Trust Deed” .
As I am using WP Multisite I can See Gravity is already storing the upload files in the gravity form folders under separate site number folders. I would however like to avoid it creating its subfolders for Year and Month of submission. ( I know there is another snippet for defining the path which I ope to use for this)
How can I apply your snippet on Multisite and for different forms? Am I right in thinking the functions.PHP sits at Network level so I think I need the snippet to take account of the site number to ensure the files are save in the folders for each site?
I would be grateful for your advice
Hi Chris,
This snippet supports GF Unique ID. Simply insert the merge tag for your Unique ID field in the
template
parameter.Instead of installing the snippet Network wide, I suggest using the Code Snippets plugin to manage the snippets on a per-site basis.
Amazing bit of code, its helping me out massively. THANK YOU!
I have a question, is it possible to pass a user input on the form into the filename?
For example, user enters an order number and uploads a file, the filename includes the order number?
Kind Regards
Hi Matt,
Most Merge tags are supported, so this should be possible if you update the template parameter in the configuration with the merge tag of the Order Number field. Something like this should get it working
'template' => '{OrderNumber:113}-{filename}'
Best,
Thanks Samuel,
Can you quickly confirm the following, in the string: {OrderNumber:113}-{filename}
What does the “:113” refer to? Is it the form field ID?
Kind Regards
Matt PS. many thanks for a super quick response on the last thread!
Hi Matt,
113 is the Field ID for the Order Number field. You may want to check out this documentation to get a better understanding of merge tags.
Best,