PHP - Windows - 文件上传后不正确(ü保存为¼等) [英] PHP - Windows - filename incorrect after upload (ü saved as ü etc.)

查看:179
本文介绍了PHP - Windows - 文件上传后不正确(ü保存为¼等)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个自制的应用程序允许多个文件上传,我将文件传递给php与AJAX,用PHP创建新的目录,移动上传的文件,并将dir位置保存到数据库。然后看看我运行的文件列表保存在数据库中的目录位置。



问题是文件来自世界各地,所以经常有一些非拉丁字符例如ü。当我以php名称回显文件名时,即使他们的名字用阿拉伯语写成,他们也被保存在服务器上,其编码名称例如是ü代替ü。当我从目录中列出文件时,我可以看到ü.txt的名称ü.txt,但是当我点击它时,服务器返回未找到错误对象(因为在服务器上它被保存为¼.txt,并将其链接为ü.txt)。



我尝试了一些建议的解决方案,例如使用iconv,但文件名仍然以相同的方式保存。



我可以发誓,当网络应用程序托管在linux上时,问题不存在,但目前我不太清楚。现在我暂时在xampp(在Windows上)运行它,似乎使用Windows-1252编码(服务器上的默认Windows'编码)保存文件名。是否有默认的Windows编码相关问题?



说实话,我不知道如何解决这个问题,我会感谢任何帮助。我应该继续尝试以不同的字符编码保存文件,还是更好地以不同的方式处理它,并更改列出已保存和编码的文件的方式?



编辑。根据(最终)关闭的错误报告,它已在php 7.1中修复。

解决方案

最后我用以下方法解决了这个问题:


  1. 当上传文件时,我用 rawurlencode()

  2. 从服务器中取出文件它们显然是URL编码的,所以我使用 urldecode($ filename)打印正确的名称

  3. a中的链接href 被自动翻译,所以例如%20成为,并且URL最终不正确,因为它链接到不正确的文件名。我决定对他们进行编码,并打印出来,结果是这样: print $ dirReceived.rawurlencode($ file); ($ dirReceived是接收到的文件被存储的目录,在代码前面定义)

  4. 我还添加了 urldecode($ filename)的下载属性,以使用UTF-8因为这样我有使用URL编码的名称保存在服务器上的文件。可以在浏览器中打开它们(非常重要,因为大多数是* .pdf),可以使用正确的名称下载它们,这样我可以上传和下载甚至带有阿拉伯语,西里尔文等的名称的文件。



    到目前为止,我测试了它,看起来不错。我正在考虑在生产代码中实现它。任何关注/想法?



    编辑



    由于没有异议,我选择我的答案为一个解决了我的问题。做一些测试后,一切看起来都很好,在客户端和服务器端。当在服务器上保存文件时,它们是被编码的,当下载它们时,它们被解码并以正确的名字保存。



    最初我使用的代码是:



     
    {
    move_uploaded_file($ _ FILES ['file'] ['tmp_name'] [$ i],
    ../filepath/$ _FILES ['file'] ['name ] [$ I]);
    }

    此方法在保存文件时导致问题,并替换每个UTF-8特殊字符用cp1252编码(ü保存为¼等),所以我添加了一行,并替换了以下代码:

      for($ i = 0; $ i< count($ _ FILES ['file'] ['name']); $ i ++)
    {
    $ fname = rawurlencode($ _ FILES ['file'] [ '名称'] [$ I]);
    move_uploaded_file($ _ FILES ['file'] ['tmp_name'] [$ i],
    ../filepath/$ fname);
    }

    这允许我使用URL编码在服务器上保存任何文件名(%和2十六进制)与cp1252和UTF-8兼容。



    要列出保存的文件,我使用的文件路径我保存在数据库中并列出文件。我正在使用以下代码:

      if(is_dir($ dir)){
    if($ dh = opendir ($ dir)){
    while(($ file = readdir($ dh))!== false){
    if(is_file($ dir。$ file)){
    $ b $文件$$$文件&$$文件&$$文件。 li>< br />;

    }
    }
    closedir($ dh);
    }
    }

    由于URL编码文件名自动解码,如果(is_dir($ dir)){
    if($ dh = opendir($ dir)){


    $ b

     
    while(($ file = readdir($ dh))!== false){
    if(is_file($ dir。$ file)){
    echo< li> a href =';
    打印$ dir.rawurlencode($ file);
    echo'download ='。 urldecode($ file)。'>。urldecode($ file)。< / a>< / li>< br />;
    }
    }
    closedir($ dh);
    }
    }

    我不知道这是否是最好的方式要解决它,但是完美的工作,我也知道通常是一个很好的做法,不要使用php来生成html标签,但是目前我有一些关键的bug需要解决,所以我需要工作代码本身的出现。



    EDIT2



    同样伟大的事情是我不必更改名称的已经上传的文件,在我的情况下是一个很大的优势。


    I have this home made app that allows multiple file uploads, I pass the files to php with AJAX, create new dir with php, move there uploaded files and save the dir location to database. Then to see the files I run listing of the directory location saved in the db.

    The problem is that files come from all around the world so very often they have some non latin characters like for example ü. When I echo the filename in php names appear correctly even when they have names written in Arabic, yet they are being saved on the server with encoded names as for example ü in place of ü. When I list the files from directory I can see the name ü.txt insted of ü.txt but when I click on it server returns error object not found (since on the server it is saved as ü.txt and it reads the link as ü.txt).

    I tried some of the suggested solutions as for example using iconv, but the filenames are still being saved the same way.

    I could swear the problem wasn't present when the web app was hosted on linux, but at the moment I am not so sure about it anymore. Right now I temporarily run it on xampp (on Windows) and it seems like filenames are saved using windows-1252 encoding (default Windows' encoding on the server). Is it default Windows encoding related problem?

    To be honest I do not know how to approach that problem and I would appreciate any help. Should I keep on trying to save the files in different character encoding or would it be better to approach it different way and change the manner of listing the already saved and encoded files?

    EDIT. According to the (finally) closed bug report it was fixed in php 7.1.

    解决方案

    In the end I solved it with the following approach:

    1. When uploading the files I urlencode the names with rawurlencode()
    2. When fetching the files from server they are obviously URL encoded so I use urldecode($filename) to print correct names
    3. Links in a href are automatically translated, so for example "%20" becomes a " " and URL ends up being incorrect since it links to incorrect filename. I decided to encode them back and print them ending up with something like this: print $dirReceived.rawurlencode($file); ($dirReceived is the directory where received files are stored, defined earlier in the code)
    4. I also added download attribute with urldecode($filename) to save the file with UTF-8 name when needed.

    Thanks to this I have files saved on the server with url encoded names. Can open them in browser (very important as most of them are *.pdf) and can download them with correct name which lets me upload and download even files with names written in Arabic, Cyrillic, etc.

    So far I tested it and looks good. I am thinking of implementing it in production code. Any concerns/thoughts on it?

    EDIT.

    Since there are no objections I select my answer as the one that solved my problem. After doing some testing everything looks good on client and server side. When saving the files on server they are URL encoded, when downloading them they are decoded and saved with correct names.

    At the beginning I was using the code:

        for($i=0;$i<count($_FILES['file']['name']);$i++) 
    {
        move_uploaded_file($_FILES['file']['tmp_name'][$i],
        "../filepath/" . $_FILES['file']['name'][$i]);
    }
    

    This method caused the problem upon saving file and replaced every UTF-8 special character with cp1252 encoded one (ü saved as ü etc.), so I added one line and replaced that code with the following:

    for($i=0;$i<count($_FILES['file']['name']);$i++) 
    {
        $fname= rawurlencode($_FILES['file']['name'][$i]);
        move_uploaded_file($_FILES['file']['tmp_name'][$i],
        "../filepath/" . $fname);
    }
    

    This allows me to save any filename on server using URL encoding (% and two hexadecimals) which is compatible with both cp1252 and UTF-8.

    To list the saved files I use filepaths I have saved in DB and list them for files. I was using the following code:

        if (is_dir($dir)){
      if ($dh = opendir($dir)){
        while (($file = readdir($dh)) !== false){
            if(is_file($dir . $file)){
    
        echo "<li><a href='".$dir.$file."' download='".$file ."'>".$file."</a></li><br />";
    
        }
    }
        closedir($dh);
      }
    }
    

    Since URL encoded filenames were decoded automatically I changed it to:

        if (is_dir($dir)){
      if ($dh = opendir($dir)){
        while (($file = readdir($dh)) !== false){
            if(is_file($dir . $file)){
                echo "<li><a href='";
                print $dir.rawurlencode($file);
                echo "' download='" . urldecode($file) ."'>".urldecode($file)."</a></li><br />";
        }
    }
        closedir($dh);
      }
    }
    

    I don't know if this is the best way to solve it but works perfectly, also I am aware that it is generally a good practice not to use php to generate html tags but at the moment I have some critical bugs that need addressing so first that and then I'll have to work on the appearance of the code itself.

    EDIT2

    Also the great thing is I do not have to change names of the already uploaded files which in my case is a big advantage.

    这篇关于PHP - Windows - 文件上传后不正确(ü保存为¼等)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆