Search code examples
phpencodingspecial-charactersphp-ziparchive

set the right encoding for file name from database with speical character


I am trying to create file with data from my database. And I'm having a hard time trying to figure out how to convert to the right encoding for windows file name.

The database is in latin1_german2_ci, which contains german character like ä,ö,ü. Now I need to get data from the database and construct a file from it. for exampe I got $name from database with $name = "zäng" and "$id = "123"

first:

$folder_name = $id . ' - ' . $name;
mkdir($folder_name);
$file_name = $folder_name . '/' . $id;
file_put_contents($file_name . '.lic', $contents);

this create the folder 123 - zäng, which is correct. and some files are added to the folder like 123.lic, 123.rom...

Next Step, I want to create a zip file with same name:

$zip = new ZipArchive();
$zip_name = $folder_name . '.zip';
$zip->open($zip_name, ZipArchive::CREATE | ZipArchive::OVERWRITE)
// to confirm its working, add an empty folder to the zip
$zip->addEmptyDir("testfolder");

this create a file names 123 - zäng.zip with subfolder testfolder. works perfectly too.
Now it happens something strange, I have to create a subfolder with the same name as the zip-file, and add some files to the subfolder. I try to achieve this with addFile:

$zip->addFile($file_name . '.lic', $folder_name . '/' . $id . '.lic');

which should create something like this:

123 - zäng.zip/123 - zäng/123.lic

but instead, the folder I created in zip file got the name RI15120201 - zõng, the special character is wrong. In ZipArchive-API, someone said

ZipArchive uses IBM850 encoding for filenames (localname). For filenames with special characters such as (é) é which appears at 0xE9 in the ISO-8859-1, it is at 0x82 in IBM850. I had to call iconv('ISO-8859-1', 'IBM850', 'Québec') to get correct file names.

additionally, I found out that

latin1 (cp1252 West European) collations:

latin1_bin

latin1_danish_ci

latin1_german1_ci

latin1_german2_ci

so I changed the code:

iconv('cp1252', 'ibm850', $name);
$folder_name = $id . ' - ' . $name;
mkdir($folder_name);
$file_name = $folder_name . '/' . $id;
file_put_contents($file_name . '.lic', $contents);

but it didn't change anything. What am I missing? And why are mkdir and $zip->open working without converting the encoding?


Solution

  • It is because you don't assign new value which is returned by iconv()

    Change

    iconv('cp1252', 'ibm850', $name);
    

    to

    $name = iconv('cp1252', 'ibm850', $name);
    

    You'll probably need to do the same with $contents