26

I'm Vietnamese and i want to upload a utf-8 filename like

Tên Tệp Tiếng Việt.JPG

Here is my code

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
<head> 
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 
<title>utf-8</title> 
</head> 

<body> 
<?php
    if(isset($_POST["submit"])) { 
       if($_FILES["upload"]["error"] > 0 ) echo "FILE ERROR!"; 
       else 
         { 
           $base_dir = "D:/"; 
           $fn = $_FILES["upload"]["name"]; 

           $fn2 = $base_dir.$fn;

           move_uploaded_file($_FILES["upload"]["tmp_name"],$fn2); 
         } 
     } 
?> 
<form action="" method="post" enctype="multipart/form-data" name="form1" id="form1"> 
  <input type="file" name="upload" id="upload" /> 
  <input type="submit" name="submit" id="submit" value="Send" /> 
</form> 
</body> 
</html> 

but when i upload that i see on my computer D:\ has a file like

Tên Tệp Tiếng Việt.JPG

How to fix that thanks

Thein Hla Maw
  • 685
  • 1
  • 9
  • 28
DeLe
  • 2,442
  • 19
  • 88
  • 133
  • 2
    On Windows you may have to use iconv() to convert it into ucs2 – Ja͢ck Aug 13 '13 at 08:40
  • @Jack I try ` $fn2 = iconv("UTF-8","ucs2", $base_dir.$fn) ;` but get error iconv(): Wrong charset, conversion from `UTF-8' to `ucs2' is not allowed ? – DeLe Aug 13 '13 at 08:44
  • 1
    It's `UCS-2` actually :) – Ja͢ck Aug 13 '13 at 08:45
  • i edit that to $fn2 = iconv("UTF-8","UCS-2", $base_dir.$fn); but i get new error `move_uploaded_file(): Filename cannot be empty ..` and `move_uploaded_file(): Unable to move 'E:\PHP\Xampp\tmp\php6B2C.tmp' ...` ? what is wrong – DeLe Aug 13 '13 at 08:49
  • Which operating system you are using. With your code check out you system settings also because at the code part it look fine but at the os i am not sure you enable all the things – Simmant Aug 28 '13 at 05:45
  • @simmant I using window8, english US keyboard ? – DeLe Aug 28 '13 at 06:42
  • 1
    First things first. Can you *`echo`* the filename you receive on the server? Test whether the filename is *uploaded* encoded in UTF-8? Because *that* part is likely working. The problem is how PHP interacts with the file system when writing files, which basically depends on whatever the underlying filesystem does, which may be pretty ugly and complex in case of Windows. If the filename is *uploaded* fine in UTF-8 the question becomes *"how to write a filename in UTF-8"*, the answer to which may not be pretty. – deceze Aug 28 '13 at 07:22

9 Answers9

16

I'm on Windows 8 chinese version, and I deal with similar problem with this:

$filename = iconv("utf-8", "cp936", $filename);

cp stands for Code page and cp936 stands for Code page 936, which is the default code page of simplified chinese version of Windows.

So I think maybe your problem could be solved in a similar way:

$fn2 = iconv("UTF-8","cp1258", $base_dir.$fn);

I'm not quite sure whether the default code page of your OS is 1258 or not, you should check it yourself by opening command prompt and type in command chcp. Then change 1258 to whatever the command give you.

UPDATE

It seems that PHP filesystem functions can only handle characters that are in system codepage, according to this answer. So you have 2 choices here:

  1. Limit the characters in the filename to system codepage - in your case, it's 437. But I'm pretty sure that code page 437 does not include all the vietnamese characters.

  2. Change your system codepage to the vietnamese one: 1258 and convert the filename to cp1258. Then the filesystem functions should work.

Both choices are deficient:

Choice 1: You can't use vietnamese characters anymore, which is not what you want.

Choice 2: You have to change system code page, and filename characters are limited to code page 1258.

UPDATE

How to change system code page:

Go to Control Panel > Region > Administrative > Change system locale and select Vietnamese(Vietnam) in the drop down menu.

Community
  • 1
  • 1
Inglis Baderson
  • 779
  • 4
  • 12
  • 1
    +1 because I think this answer is going in the right direction. Since you'll need to choose the right codepage for the set of characters you want to use, this is of course hard to generalize. – deceze Aug 28 '13 at 08:07
  • 1
    i try and give: `Active code page: 437`, and i change to `$fn2 = iconv("UTF-8","cp437", $base_dir.$fn);` and give error like `Notice: iconv(): Detected an illegal character in input string in ` and some warning like `Warning: move_uploaded_file(): Filename cannot be empty` ...? – DeLe Aug 28 '13 at 08:30
  • @trungkien Now I have no idea either. Try `cp1258`, maybe? – Inglis Baderson Aug 28 '13 at 09:42
  • that's running look better than before :( but still not utf-8 – DeLe Aug 28 '13 at 09:59
  • i follow http://superuser.com/questions/269818/change-default-code-page-of-windows-console-to-utf-8 to change codepage to `1258`. The first I just change in `HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\CodePage\OEMCP`. But the second, i can't find `Autorun` in `HKEY_LOCAL_MACHINE\Software\Microsoft\Command Processor\Autorun` ? – DeLe Aug 29 '13 at 12:28
  • I just create Autorun string in `Command Processor` and put `@chcp 1258>nul` value. after i restart my computer and type `chcp` on `cmd` and get `Active code page: 1258` But when i run upload again then it's still not vietnamese file name :( – DeLe Aug 29 '13 at 12:57
  • @trungkien That method won't work because it only changes the code page of the command prompt. See my update. – Inglis Baderson Aug 29 '13 at 16:12
5

This meta has no effect:

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

because the web server has already sent Content-Type header, and thus decided what the encoding will be. Web browsers send forms in the same encoding. The meta is useful when user is off-line.

So you have to sned http header Content-Type by yourself:

<?php header("Content-Type: text/html; charset=utf-8"); ?>

ensure that you put this before any html, content or whatever is sent.


Alternatively, accept-charset tag on form should work as weel:

 <form accept-charset="utf-8"> 
Zaffy
  • 16,801
  • 8
  • 50
  • 77
  • i added at first of file (file is my code in my question) but nothing work :( – DeLe Aug 26 '13 at 07:48
  • @trungkien What browser are you using ? Try to watch network traffic and especially when you send form, check the sent (from browser) `content-type` header. Is there a `charset` ? You can also try adding `accept-charset="utf-8"` to `
    `
    – Zaffy Aug 26 '13 at 07:51
  • I'm using firefox. How to watch network traffic?. I using firebug and i go to: `Net>All>Headers>Response Headers` and i see `Content-Type text/html; charset=utf-8` on `Response Headers`. I try to add `accept-charset="utf-8"` but not working. Here is my `upload.php` file http://jsfiddle.net/nnBwV/ – DeLe Aug 26 '13 at 09:37
  • @trungkien Okay, I meant `content-type` in `Request Hedears`, take a look there. – Zaffy Aug 26 '13 at 10:08
  • in option `Request Headers From Upload Stream` has `Content-Type multipart/form-data; boundary=---------------------------18199138701329` ?? – DeLe Aug 26 '13 at 11:25
  • @trungkien that's it. There is no `charset`, which means that it is the same as the page is. My main suspect now is that your file is not saved as utf-8 - check that, also check php ini directive called `default_charset`. Ok, navigate to `Post` tab and find `source` category and line which looks like this: `Content-Disposition: form-data; name="upfile"; filename="your_file.txt"` Is the filename of correct encoding ? – Zaffy Aug 26 '13 at 11:58
  • in php.ini has: `;default_charset = "UTF-8"`. i don't understand your mean `navigate to Post tab and find ..` what is `Post` tab? – DeLe Aug 26 '13 at 12:30
  • @trungkien delete the `;` in the php.ini. I meant Post tab in firebug – Zaffy Aug 26 '13 at 18:12
  • i have been remove `;` but it still not working. I don't find any tab has name `Post` :( – DeLe Aug 27 '13 at 02:13
  • accept-charset is important, apparently if not set it defaults to the document's charset, which may not be the correct one. Spent an hour getting utf-8 to work correctly on multipart fileupload, every time. – Sarsaparilla Apr 28 '15 at 14:50
3

I am Persian and I have same problem with utf-8 character in my language. I could solve my problem with this code:

$fn = $_FILES["upload"]["name"]; // name of file have some utf-8 characters
$name=iconv('utf-8','windows-1256', str_replace('ی', 'ي', $fn));
move_uploaded_file($_FILES["upload"]["tmp_name"],$name );

I am not sure about vientam language but maybe you can use the same code as above with a few changes:

$fn = $_FILES["upload"]["name"]; // name of file have some utf-8 characters
$name=iconv('utf-8','cp936', $fn);
move_uploaded_file($_FILES["upload"]["tmp_name"],$name );
rezaSefiddashti
  • 134
  • 1
  • 9
1

The only solution I have found so far.. (2014 year):

1) I dont store files on my FTP in UTF-8 string. Instead, i use this function, to rename the uploaded files:

<?php
// use your custom function.. for example, utf8_encode
$newname  = utf8_encode($_FILES["uploadFile"]["name"]);
move_uploaded_file($_FILES["uploadFile"]["tmp_name"], $newname);
?> 

2) Now you can rename (or etc) $newname;

T.Todua
  • 53,146
  • 19
  • 236
  • 237
0

For a start get detecting filename encoding (before uploading).

print_r($_FILES["upload"]);

Insert filename to decoder and check encoding.

iproger
  • 9
  • 2
0

Sorry! your question is about file name.

You must save your file name with iconv but read without this.

for saving:

<?php
$name = $_FILES['photo']['name'];
$unicode = iconv('windows-1256', 'utf-8', $name);
move_uploaded_file($_FILES['photo']['tmp_name'], 'photos/' . $name);
mysql_query("INSERT INTO `photos` (`filename`) VALUES ('{$unicode}')");
?>

for reading:

<?php
$images = mysql_query('SELECT * FROM `photos`');
if($images && mysql_num_rows($images) > 0) {
    while($image = mysql_fetch_assoc($images)) {
        $name = iconv('utf-8', 'windows-1256', $image['filename']);
        echo '<img src="photos/' . $name . '"/>';
    }
    mysql_free_result($images);
}?>
Danoosh
  • 169
  • 2
  • 7
-1
function convToUtf8($str) 
{ 
if( mb_detect_encoding($str,"UTF-8, ISO-8859-1, GBK")!="UTF-8" ) 
{ 

return  iconv("gbk","utf-8",$str); 

} 
else 
{ 
return $str; 
} 

}


$filename= convToUtf8($filename) ;
Saurabh Chandra Patel
  • 12,712
  • 6
  • 88
  • 78
-2

try this

$imgname     = $_FILES['img'] ['name'] ;
$imgsize     = $_FILES['img'] ['size'] ;
$imgtmpname  = $_FILES['img'] ['tmp_name'] ;
$imgtype     = $_FILES['img'] ['type'] ;
$size     = 1024;
$imgtypes    = array('image/jpeg','image/gif','image/png');
$folder = "up";

if(empty($imgname)){
  echo "Shose ur photo";
}else if(!in_array($imgtype,$imgtypes)){
  echo "this photo type is not avalable";
}else if($imgsize > $size){
  echo "this photo is dig than 6 MB";
}else if($imgwidth > 5000){
echo "the file is to big";
}
else{
 move_uploaded_file($imgtmpname, $folder, $filename); 
}
Mahmoud Samy
  • 270
  • 2
  • 11
-3

You can use this

$fn2 = basename($_FILES['upload']['name']);
guihknx
  • 11
  • 1
  • 5