When building a form to collect wedding photos with Gravity Forms, I ran into a common issue: using the {all_fields} merge tag in notifications simply displayed the uploaded file names — but they weren’t clickable links. With multiple file uploads enabled, attaching every photo to the email wasn’t practical either, since it made messages heavy and slow to send.
The solution was to add a small custom code snippet that detects file upload fields (including multi-file uploads) and automatically converts each uploaded image into a clickable download link in the notification email. This way, recipients can view or download photos directly from the email without any bulky attachments clogging their inboxes. A simple fix that keeps things lightweight, user-friendly, and elegant.
<?php
/**
* Converts file upload values in {all_fields} to clickable links and prevents attachments.
*/
// 1) Make file upload fields clickable inside {all_fields}.
add_filter( 'gform_merge_tag_filter', function( $value, $merge_tag, $options, $field, $raw_value, $format ) {
// Only adjust values when rendering {all_fields} and the field is a file uploader (including multi-file).
if ( 'all_fields' !== $merge_tag ) {
return $value;
}
if ( ! $field instanceof GF_Field ) {
return $value;
}
// File Upload field types in GF.
$is_file_field = (
isset( $field->type ) && (
'fileupload' === $field->type || 'post_image' === $field->type
)
);
if ( ! $is_file_field ) {
return $value;
}
if ( empty( $raw_value ) ) {
return $value;
}
// Build an array of URLs (handles single- and multi-file).
$urls = [];
// Multi-file uploads store JSON; single-file is a string URL.
if ( is_string( $raw_value ) && strlen( $raw_value ) && ( $raw_value[0] === '[' || $raw_value[0] === '{' ) ) {
$decoded = json_decode( $raw_value, true );
if ( is_array( $decoded ) ) {
// For multi-file, GF stores an array of URLs.
$urls = array_values( array_filter( array_map( 'strval', $decoded ) ) );
}
}
if ( empty( $urls ) ) {
// Treat as single-file URL.
$urls = [ $raw_value ];
}
// Create a tidy unordered list of links.
$items = [];
foreach ( $urls as $url ) {
$href = esc_url( $url );
// Use the filename as the link label.
$path = wp_parse_url( $url, PHP_URL_PATH );
$label = $path ? wp_basename( $path ) : $href;
$items[] = sprintf( '<li><a href="%1$s">%2$s</a></li>', $href, esc_html( $label ) );
}
// Return HTML; GF notifications are HTML-capable.
return ! empty( $items ) ? '<ul>' . implode( '', $items ) . '</ul>' : $value;
}, 10, 6 );
/**
* 2) Ensure uploads are NOT attached to the email,
* even if someone checks the "Enable file upload attachments" box later.
*/
add_filter( 'gform_notification', function( $notification, $form, $entry ) {
// Gravity Forms sets attachments via $notification['attachments'] when the notification
// has "Enable file upload attachments" toggled on. We’ll clear them to force link-only behavior.
if ( isset( $notification['attachments'] ) && is_array( $notification['attachments'] ) && $notification['attachments'] ) {
$notification['attachments'] = [];
}
// Some versions/plugins use this flag; force it off just in case.
if ( isset( $notification['enableAttachments'] ) ) {
$notification['enableAttachments'] = false;
}
return $notification;
}, 10, 3 );