Rainlab Builder插件图片上传:保留原文件名的SEO优化问询
Got it, let's fix that filename issue so you can retain original image names for better SEO. Rainlab Builder relies on October CMS's file attachment system, which defaults to hash-based filenames to avoid conflicts—but we can override that behavior easily. Here's how:
Step 1: Locate Your Builder-Generated Model File
Head to your plugin's directory where the model lives. Typically, this path looks like plugins/[your-plugin-slug]/models/[your-model-name].php. For example, if your plugin is portfolio and the model is Project, it'll be plugins/portfolio/models/Project.php.
Step 2: Modify the Attachment Configuration
Find the $attachOne or $attachMany array in your model where the image upload is defined. By default, it might look like this:
public $attachOne = [ 'project_image' => ['System\Models\File'] ];
We'll add a custom callback to preserve the original filename. Update the array to include a file_name handler:
public $attachOne = [ 'project_image' => [ 'System\Models\File', 'file_name' => function($file) { // Grab the original filename from the uploaded file $originalName = $file->getClientOriginalName(); // Optional: Prevent overwriting existing files by adding a counter suffix $counter = 1; $targetPath = storage_path('app/uploads/public/' . $originalName); while (file_exists($targetPath)) { $name = pathinfo($originalName, PATHINFO_FILENAME); $ext = pathinfo($originalName, PATHINFO_EXTENSION); $originalName = "{$name}_{$counter}.{$ext}"; $targetPath = storage_path('app/uploads/public/' . $originalName); $counter++; } return $originalName; } ] ];
Key Notes:
- The callback uses
getClientOriginalName()to pull the user's original filename. - The optional loop checks for existing files and appends a counter (e.g.,
my_image_2.jpg) to avoid overwrites. Skip this part if you don't mind replacing duplicates.
Step 3: Sanitize Filenames (Optional but Recommended)
To avoid issues with special characters or malicious filenames, add sanitization to the callback:
// Clean up the original name to remove unsafe characters $originalName = preg_replace('/[^a-zA-Z0-9_\-\.]/', '', $file->getClientOriginalName());
Step 4: Clear Cache and Test
After making changes, clear October CMS's cache to apply the updates:
php artisan october:cache:clear
Now upload an image like my_image.jpg through your Builder backend form—it should save to storage/uploads/public/my_image.jpg (or with the counter suffix if a duplicate exists) instead of the hash-based filename.
Alternative: Reusable Custom File Model
If you need this behavior across multiple models, create a custom File model to avoid repeating code:
- Create
plugins/[your-plugin]/models/CustomFile.php:
namespace YourPlugin\Models; use System\Models\File as BaseFile; class CustomFile extends BaseFile { protected function getFileName() { $originalName = preg_replace('/[^a-zA-Z0-9_\-\.]/', '', $this->getClientOriginalName()); // Add duplicate check here if needed return $originalName; } }
- Use this model in your attachments:
public $attachOne = [ 'project_image' => ['YourPlugin\Models\CustomFile'] ];
Pro tip: If you're using
$attachMany, the same logic applies—just update the array accordingly.
内容的提问来源于stack exchange,提问作者Mr Pickles

