Search code examples
androidnanohttpd

Why do I get messy code of chinese filename when I upload files to NanoHTTPD server in Android?


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());
        }

    }      

Solution

  • 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);