Jump to content

Recommended Posts

Windows and PHP have never gotten along when it comes to non-ASCII filenames. PHP is not a Unicode program (as far as Windows knows) so it gets special treatment when it comes to filenames, but that special treatment can be a big problem.

 

The best solution I know is this class. It requires the com_dotnet extension so if you cannot load that then you're out of luck.

You use it like this:

// say you want to write to a file named "C:\العربية.ext"
$filename = "C:\\العربية.ext";

// first you need to make sure the filename is UTF-8 encoded. in your case it probably is
// if not then you can use
$filename = mb_convert_encoding($filename, "UTF-8", "original character encoding");

// now you detect windows systems. this is good for portability
if (strncasecmp(PHP_OS, "WIN", 3) == 0) {
	// WindowsStreamWrapper requires the com_dotnet extension
	if (extension_loaded("com_dotnet") || function_exists("dl") && dl("com_dotnet")) {
		// if you do not have autoloading,
		//require_once("path/to/Patchwork/Utf8/WindowsStreamWrapper.php");

		// while you can use the class normally, it is easier to use it as a stream wrapper
		// you can use any label for the stream wrapper name. I chose "winfs"
		stream_wrapper_register("winfs", "Patchwork\\Utf8\\WindowsStreamWrapper");
		$filename = "winfs://" . $filename;
	}

	// if we cannot load the extension, ASCII filenames are safe and we don't have to worry about them
	// this detects bad filenames by looking for high bytes: 127-255
	else if (preg_match('/[\x7F-\xFF]/', $filename)) {
		// there is no good solution. you may decide to raise a fatal (!) error
		//trigger_error("The com_dotnet extension is required for non-ASCII filenames but cannot be loaded", E_USER_ERROR);
		//exit;

		// or you can substitute a different filename and let the code continue
		// this is better in practice because a file with the wrong name is better than no file at all
		$filename = dirname($filename) . "\\" . uniqid(time(), true) . "." . pathinfo($filename, PATHINFO_EXTENSION);
		// (be careful: the file extension may not be ASCII either! in this code I assume it is)
	}
}

// now you can write to the file the same way you normally would. for example, file uploads still use move_uploaded_file():
move_uploaded_file($_FILES["foo"]["tmp_name"], $filename);
Edited by requinix
This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.