Stopping symfony from screwing up uploaded files names

Flattr this
Tweet this: Stopping symfony from screwing up uploaded files names
Dent this: Stopping symfony from screwing up uploaded files names
Datum: 18.08.2010 22:05:09

Symfonys behaviour to rename uploaded files with a sha1-hash of the original filename and a randomnumber between 11111 and 99999 [why those numbers ?], ( done in sfValidatedFile::generateFilename ) is pretty ugly. No more seo-friendly filenames, filenames where you can actually have a clue about what's behind an url or how the creator supposed it to be named.

Why symfony has, under some circumstances to change the filesname is pretty easy to understand. Uploading a file with the same name should not throw an error or overwrite the other file, so changing it has to be done in some way under some circumstances. So overwriting the method and returning just the original name would not really help.
What we need is a way to change the name for files, but ONLY if there already exists a file with that name.

The easiest way that came to my mind was, if the file already exists, appending something. Since collusions can happen more than once, appending just a fixed value won't help. Since i don't really like adding some random number and hoping no collusion happens later, I wanted an incrementing number to be appended to the filename.
Spoken in code it can look like this:

class myValidatedFile extends sfValidatedFile
{

  /**
   * Generates a non-random-filename
   *
   * @return string A non-random name to represent the current file
   */
  public function generateFilename()
  {
    $filename = $this->getOriginalName();

    $ext = $this->getExtension($this->getOriginalExtension());
    $name = substr($this->getOriginalName(), 0, - strlen($ext));
    $i = 1;
    while(file_exists($this->getPath() . '/' .  $filename)) {
      $filename = $name . '-' . $i . $ext;
      $i++;
    }
    return $filename;
  }
}

It checks if the file already exists if not, it tries to append "-" followed by an incrementing number, it checks again, increments the number, checks again, until it finds a free number. No random number, an incrementing number.
Now the sfValidatorFile has to use this class instead of sfValidatedFile, that can be done by passing its name in on creation of the sfValidatorFile:

public function configure()
{
  $this->widgetSchema['image'] = new sfWidgetFormInputFileEditable(array(
    'label' => 'Field Name',
    'file_src' => '/uploads/images/'.$this->getObject()->getImage(),
    'is_image' => true,
    'edit_mode' => !$this->isNew(),
    'template' => '%file% %input% %delete% %delete_label%'
  ));
  
  $this->validatorSchema['image'] = new sfValidatorFile(array(
    'required'   => false,
    'mime_types' => 'web_images',
    'path'       => sfConfig::get('sf_upload_dir').'/images',
    'validated_file_class' => 'myValidatedFile',
  ));
  
  // delete checkbox
  $this->validatorSchema['image_delete'] = new sfValidatorPass();
}

Trackbacks (0)

Trackbackurl: http://www.robo47.net/trackback/blogentry/204

Es sind keine Trackbacks vorhanden.


Kommentare (3)

  • Kommentar von Christian am 19.08.2010 06:47:57
    Gravatar Christian

    That's exactly what I used to do. But by now I use sfImageTransformExtraPlugin for all images which means I never show any image from the uploads folder directly. And using the doctrine source I maintain SEO friendly URLs still.

    I will write a blog post about it tomorrow I guess. :)

    Still very useful your post for other file types like PDFs for download and such!


  • Kommentar von robo47 am 19.08.2010 11:24:20
    Gravatar robo47

    I don't show them directly from the upload-folder, but since i use the standard-non-doctrine-route, the last part of the route always is the file-name.

    I will have a look into the doctrine source at the weekend too and see if that would satisfy my needs, but probably it will complicate things for the apps i am currently working on, since there are db-entries with often many images, 5 or more per object.


  • Kommentar von Christian am 20.08.2010 06:15:32
    Gravatar Christian

    Finished part 2 of the workshop. SEO friendly URLs / Doctrine models / more than one image.

    http://test.ical.ly/2010/08/20/workshop-integrating-sfimagetransformextraplugin-into-your-symfony-backend-application-–-part-2/

    Let me know what you think.


Die Kommentare zu diesem Beitrag sind gesperrt.

You liked it ? Link it on your homepage or blog: