Prevent one image from overwriting another in the input file

Asked

Viewed 57 times

-1

I have this code:

$img = $_FILES['file']['name'];
$diretorio = "imagens/";
$tmp = $_FILES['file']['tmp_name'];
move_uploaded_file($tmp, $diretorio.$img);

If I put, for example: ball.png and another user put ball.png after, the image of it will change mine. I would like that if there is already this file in my images folder and in my database, it appears as, for example: ball(1). png, then ball(2). png and so on.

  • I think you are going the more complicated side. It would not be better to check in the bank if the name of the image exists and register another name?

  • 2

    Or you can rename files based on a unique value, such as uniqid(), for example.

  • As commented by @Andersoncarloswoss, you better use a name you control, not the uploader. Even, if you take advantage of the original name you will have other problems with special characters.

  • it would be better to do something like put the current timestamp along with the file name, which will always be different.

  • @Louie or simply add a prefix, like a timestamp, for example 20171218105930_ (year/month/day/hour/min/second)

  • Dvd the problem is that imagine after a time when the site grow and there are millions of images. The user will have to keep trying to guess which image path does not exist in the database.

  • Anderson, I thought of renaming later as you said, only it’s kind of complicated because I wanted to put the value of the image path in the alt of the img tag so that people with visual impairment can understand what the image is about.

  • Where you save the directory?

  • Dvd the problem is that imagine after a time when the site grow and there are millions of images. The user will have to keep trying to guess which image path does not exist in the database. You save the images in different directories?

  • The idea of timestamp is good, I had not thought about it, but there is the possibility of putting as I commented? " ball(1). png", because I see that when I download or upload an image that has the same name on my pc or google drive.

  • Dvd, no, it’s in one directory only: "images/".

  • So, as I said in my first comment, change the name of the submitted image if there is already one, if that’s what you want to do.

  • Louie, but the problem is not even this... the right one is you treat the name of the file sent and not save it with the name that was sent. And if the user sends an image with the name sdjhdsjhdsjhjdsjsdhjds dsdshdsghds ghdshdsg.png? It’ll mess up your website.

  • If the user mocks, just punish or block him. When it posts something, I know who is posting and it also has a report button that other people can use to report a particular user. If anyone acts inappropriately on stackoverflow, the staff will punish. The same thing is if anyone wants to mock my site, I will punish.

Show 9 more comments

1 answer

2


Just use is_file and create a recursive function to avoid duplicating

function increment_name($path)
{
    //Se o arquivo não existir o nome será aceito
    if (!is_file($path)) {
        return $path;
    }

    //Pega as informações do PATH
    $info = pathinfo($path);

    //Pega o nome sem extensão
    $name = $info['filename'];

    /*
     * Se não houver um formato como "x (1).txt"
     * então inicia do zero para incrementar 1
     */
    $current = 0;


    /*
     * Verifica se já existe algo como "x (1).txt"
     * se existir pega o numero e manda os valores do regex para $out
     */
    if (preg_match('#\((\d+)\)$#', $name, $out)) {
        //Pega o numero que estava entre parenteses
        $current = $out[1];

        //Remove o numero e os parenteses do final
        $name = rtrim(substr($name, 0, -strlen($current)-2));
    }

    //Incrementa um numero
    $name .= ' (' . (++$current) . ')';

    //Checa recursivamente se o NOVO nome já existe ou não
    return increment_name($info['dirname'] . '/' . $name . '.' . $info['extension']);
}

//Usando

$img = $_FILES['file']['name'];
$diretorio = "imagens/";
$tmp = $_FILES['file']['tmp_name'];

$new_name = increment_name($diretorio.$img);

move_uploaded_file($tmp, $new_name);

Using uniqid()

Following the suggestions of the comments, you can use the uniqid() only she has a problem, she is not 100% guaranteed because it uses "time", so it can get around the problem you try to apply a rand() and also check if the name already exists, making a recursive check

I created an example:

function create_ufilename($name, $path = '.')
{
    //Pega a extensão da imagem original
    $ext = pathinfo($name, PATHINFO_EXTENSION);

    //Gera um nome baseado no tempo
    $id = uniqid(rand(1, 100));

    //Gera o caminho
    $path .= '/' . $id . '.' . $ext;

    //Se existir tentará novamente, caso contrário retornará o novo nome
    return is_file($path) ? create_ufilename($name, $path) : $path;
}

//Usando

$img = $_FILES['file']['name'];
$diretorio = "imagens/";
$tmp = $_FILES['file']['tmp_name'];

$new_name = increment_name($diretorio.$img);

//Deve passar o nome da imagem e a pasta que deseja salvar, assim:
$salvar = create_ufilename($img, $diretorio);

move_uploaded_file($tmp, $salvar);
  • the use of the function tempnam would be more useful instead of uniqid()?

  • @Everson if I were to use this would have to apply chmod to everything :/ ... besides I think the behavior in Win and Linux is different.

  • 1

    Got it, thanks :)

  • Whoa, I got it here. Thanks ;)

Browser other questions tagged

You are not signed in. Login or sign up in order to post.