-1

I use NanoHTTPD as web server in my Android App, I upload multiple files include chinese filename to server client using Code A.

But I get the messy code of chinese filename in Code B, how can I fix the pr oblem? Thanks!

Messy code screenshot

enter image description here

Code A

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>WiFi File Transfer</title>
    <meta charset= "utf-8"/>  
</head>

<body>
        <div id="content">     

            <form action="" method="post" enctype="multipart/form-data">
                <input type="file" name="myupload" multiple="multiple" />
                <input type="submit" value="Upload Files"/>
            </form>                                       


        </div> 

</body>
</html>

Code B

@Override
public Response serve(IHTTPSession session) {

        String uri = session.getUri();

        MURLPar mURLPar=new  MURLPar(mContext);
        SetMURLParValue(mURLPar,session);

        Method method = session.getMethod();
        if (Method.POST.equals(method)) {

            Map<String, String> files=null;
            try {

                files = new HashMap<String, String>();
                session.parseBody(files);
            }catch (Exception e) {                
            }


            ActionUploadFiles(mURLPar,files,session);
            ...

}      


 private void ActionUploadFiles(MURLPar mURLPar, Map<String, String> files,IHTTPSession session){
        File upload = new File(FileFolderHelper.GetPhysicsCurrentPath(mURLPar) +"/Upload");

        try{
            Set<String> keys = files.keySet();

            for (String key:keys) {
                String location = files.get(key);
                File source = new File(location);
                String filename=session.getParms().get(key);

                //It will be messy code when uploaded filename is chinese!    
                filename=java.net.URLDecoder.decode(filename, "utf-8"); 

                File target = new File(upload.getPath(),filename);

                FileUtils.copyFile(source,target);
            }
        }
        catch (Exception e) {
            Utility.LogError("Upload Error: "+ e.getMessage());
        }

    }      
HelloCW
  • 843
  • 22
  • 125
  • 310
  • I do not see messy file names. – greenapps Feb 28 '17 at 09:11
  • Thanks ! String filename=session.getParms().get(key) will be messy code when uploaded filename is chinese! – HelloCW Feb 28 '17 at 11:19
  • Can I encode filename before upload multiple files ? – HelloCW Mar 01 '17 at 02:17
  • it's messy because the encoding is set to `utf-8`. Look at the solution here on how to properly encode Chinese characters. http://stackoverflow.com/questions/6838446/utf-encoding-for-chinese-charactersjava?answertab=active#tab-top – ᴛʜᴇᴘᴀᴛᴇʟ Mar 03 '17 at 00:41
  • Thanks! but http://stackoverflow.com/questions/6838446/utf-encoding-for-chinese-charactersjava?answertab=active#tab-top don't work for me. I upload file (include English filename files and Chinese filename files) from client side to NanoHTTPD server, the Chinese filename is messy code, but English filename is OK – HelloCW Mar 03 '17 at 07:01
  • 1
    Please place a file on the internet with a chinese file name which we can download and test with. Also post the chinese filename here. – greenapps Mar 04 '17 at 09:50
  • This is a Chinese filename, I place it to a ZIP file at https://www.dropbox.com/s/r9hi56wt51ucue2/TestFilename.zip?dl=0 – HelloCW Mar 05 '17 at 13:37
  • So is the filename **`-Ò¦+.txt`** supposed to read as **`你好世界.txt`**? Nope? Maybe you should say what is expected Chinese characters of filename and also for that internal text. Anyway right now it looks like an encoding issue. Does using `meta charset= "utf-16"` help? Anyways your text file does **not** even begin with bytes `FF FE` or even `FE FF` so there is nothing here to tell other systems that this is Chinese characters. Now even Android thinks the byte numbers make text like ����... – VC.One Mar 07 '17 at 15:04
  • This has been a very useful question / answer to me, why the negatives? – biquillo Apr 24 '18 at 17:51

1 Answers1

6

The filename is not URL encoded. NanoHTTPD looks in the Content-Type header to find a charset directive. Unfortunately it seems that for multipart/form-data the only valid directive is boundary, and NanoHTTPD falls back on ASCII.

Besides modifying NanoHTTPD's ContentType.getEncoding() method, the only workaround I can think of is to:

  1. Add accept-charset="UTF-8" to ensure the form encoding.

    <div id="content">
        <form action="" method="post" enctype="multipart/form-data" accept-charset="UTF-8">
            <input type="file" name="myupload" multiple="multiple" />
            <input type="submit" value="Upload Files"/>
       </form>
    

  2. Add the charset directive to the NanoHTTPD session before parsing the content, the ContentType class has a method which does exactly that:

    @Override
    public Response serve(IHTTPSession session) {
        // add "; charset=UTF-8" to the content type
        ContentType ct = new ContentType(session.getHeaders().get("content-type")).tryUTF8();
        session.getHeaders().put("content-type", ct.getContentTypeHeader());
    
        ...
    
        // no need to URL decode
        String filename=session.getParms().get(key);
    
bwt
  • 17,292
  • 1
  • 42
  • 60
  • And more, does it mean that this is a bug in NanoHTTPD ? – HelloCW Mar 08 '17 at 07:16
  • I think it's not really a bug : NanoHttpt has no way to tell wich encoding is used. On the other hand the application knows which encoding was declared in the form. It would be nice to be able to set an other default encoding than ASCII – bwt Mar 08 '17 at 09:34