Problem sending images to a folder with accented names

Asked

Viewed 204 times

0

I am sending an image to a folder and saving only the location (path) of it in the database. If for example the name I assign the image has no accents works perfectly, only when it has accents it doesn’t work. When storing in the database and showing on the website shows everything correct.

When storing in the folder I cannot fetch the respective image because the path (path) is for example "Products/joe" and so the name appears inside the folder z&A

Sending code to the database and folder:

    if(isset($_POST['upload']) && isset($_FILES['file-image'])) {
    $filetmp = mysqli_real_escape_string($_FILES["file-image"]["tmp_name"]);
    $filename = mysqli_real_escape_string($dbc, $_FILES["file-image"]["name"]);
    $filetype = mysqli_real_escape_string($dbc, $_FILES["file-image"]["type"]);
    $ProdName = mysqli_real_escape_string($dbc, $_POST['nameProduct']);
    $ProdPrice = mysqli_real_escape_string($dbc, $_POST['productPrice']);
    $ProdDescr = mysqli_real_escape_string($dbc, $_POST['descrProduct']);

    $filepath = "Products/" . $ProdName ;
    $info = getimagesize($filetmp);
    if ($info == FALSE or (empty($ProdName) or empty($ProdPrice) or empty($ProdDescr))) {
        alertError();
    }elseif ($info == FALSE and (empty($ProdName) or empty($ProdPrice) or empty($ProdDescr))) {
        alertError();
    }elseif ($info == TRUE and (empty($ProdName) or empty($ProdPrice) or empty($ProdDescr))) {
        alertError();
    }elseif ($info == TRUE and (!(empty($ProdName) or empty($ProdPrice) or empty($ProdDescr)))) {
        move_uploaded_file($filetmp, $filepath);
        $result = mysqli_query($dbc, "INSERT INTO images (img_name,img_path,img_type) Values('$ProdName','$filepath','$filetype')") or die(errorAdmin());
        $last_id = $dbc->insert_id;
        $insertProduct = mysqli_query($dbc, "INSERT INTO products (name_Product,prod_description,prod_price,img_id)
                                        Values('$ProdName','$ProdDescr','$ProdPrice','$last_id')") or die(errorAdmin());
        mysqli_query($dbc, "SET NAMES 'utf8'") or die(mysqli_error($dbc));
        if ($insertProduct == TRUE and $result == TRUE) {
            ?>
            <script type="text/javascript">
                swal({
                    title: 'Good Job',
                    text: 'Produto Criado Com Sucesso',
                    type: 'success',
                    confirmButtonText: 'Feito'
                });
            </script>
            <?php
        }
    }
    mysqli_close($dbc);
}
  • You even need the file name to contain accents?

  • Yes because it will be the name of the product, so there may be accented names

  • 1

    I suggest you use the function mysqli_set_charset(connection, charset) , where connection is your connection object and charset the type of encoding you are using in the bank. Ex.: mysqli_set_charset($conn, 'utf8').

  • where do I use this function? and that I already have in the page code the ini_set function()

  • places in php this function that @Pantera referred to

  • @A.Maia can put right after opening the connection with the bank. Or at the beginning of this your script, as a test.

  • Thanks for the help but it doesn’t work anyway

  • @A.Maia accentuation is a bit complicated, especially when it comes to database/language/file system integrations. A common practice in cases such as yours is to "clear" the name with accents, replacing the accents with pure ASCII. Solutions such as that one should help you in this.

  • @Panther thank you very much, it is then without accents. Thank you for the solution

  • 2

    Normally if you have a product database, you do not need to use the product name in the file. Use base ID instead of name, which simplifies everything.

Show 5 more comments

1 answer

4

Using accent on filenames is a bit tricky and will hardly be a portable solution.

Operating systems handle character encoding in different ways.

Linux


Linux uses binary for filenames. This means that it does not require a specific encoding to save the filename. For example if we create two files with different encodings in their names, but which are equivalent (we will talk more about this):

$ echo "foo" > $'z\xc3\xa9.txt'
$ echo "bar" > $'ze\xcc\x81.txt'

As we execute the command ls, we will have the following output:

$ ls 
zé.txt zé.txt

This means that the program that uses the filesystem needs to worry thoroughly with the encoding and normalization of characters, because if there is more than one file with the same name, but with different normalizations, which file should the program consider correct? Apart from security issues.

OSX


OSX already uses UTF-16 to encode file names. This is done transparently for the user. That is, if your program saves the file name using UTF-8, OSX will translate it to UTF-16.

Another point to consider when using OSX is how it normalizes characters. The Unicode specification defines something called equivalence and standardisation. This concept defines how the combination of characters is done in the different types of normalizations (NFD, NFC, NFKD, NFKC) for the same character. To illustrate this concept, just save a file with the correct sequence in UTF-8 of the character is (\xC3\xA9):

<?php
file_put_contents("z\xC3\xA9.txt","xyz");
?>

And we’ll check what was actually recorded:

<?php
list($file) = glob('z*');
echo urlencode($file) . "\n";
?>

We will have the following output:

ze%CC%81.txt

The OSX recorded e0xCC81 instead of 0xCCA9. This shows us that the OSX uses a normalization that uses three bytes, the e and two more bytes combined result in acute accent. These three bytes together form the letter é.

Windows


Windows also uses UTF-16 (using NTFS), with the OSX-like behavior of transparent character translation. Regarding normalization, it behaves different from OSX, if we run the same code we run on OSX we will see the correct characters in the output.

Completion


We already have here two equivalent ways of writing the same letter in Unicode. We have two more, which are beyond the scope here. The fact is that if you really want to work with accents on behalf of files, you will need some care and probably use an intermediary to save those files.

The extent lntl PHP offers a class called Normalize which allows you to control the normalization of characters. It is an interesting option if you want to intermediate these encodings.

My suggestion is that you translate accented characters to pure ASCII whenever you can.

  • 1

    Thanks for the help

  • 2

    +1 good answer, pity it is for a question that should be solved otherwise (deserved more visibility the answer). Everyone forgets the normalization of UTF-8, which is extremely boring and complex. Any small app has to be inflated with gigantic tables to stay portable. I recently explained to an acquaintance that A and A are completely different strings (strings are not normalized here currently), but he only understood when he copied and pasted into a non-Unicode code editor.

  • @Bacco, Thank you. I really did not think that the answer would be the chosen solution to the question, it is more like an alternative. But as I commented on the question that the best option was to choose not to use accents in filenames, I thought it best to explain why. Since in a comment would not have enough space to discuss the subject, I decided to put as an answer.

Browser other questions tagged

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