5

I'd like to serve the files (.html and .css files, for example) of a local folder to recreate the usual behavior of a "real" local website.

Here are two examples of applications that work how I'd like mine to work: Tiny Web Server Free and kWS - Android Web Server.

I searched a lot with Google but I couldn't find anything...

I tried with NanoHttpd but it appears we can't set a root or home directory and we are only able to return some http code by returning a Response object with the serve() method. That's not what I want.

I'd like to be able to set a root directory, for example sdcard/www/, with a index.html that includes images from the sdcard/www/img/ subfolder...

Also, I found this answer, but this is not what I want. It consists in returning the content of an .html file in a Response object with the serve() method.

How could I do what I'd like to do?

Community
  • 1
  • 1
Drarig29
  • 1,902
  • 1
  • 19
  • 42
  • `tried with NanoHttpd but it appears we can't set a root or home directory`. Of course you can. And you can of course serve files with `serve()`. – greenapps Nov 05 '16 at 16:46
  • Ok, but how? If we can, I didn't find it... :) – Drarig29 Nov 05 '16 at 16:47
  • Dont understand your problem. NanoHttpD can serve files from every directory. Just take the right path. – greenapps Nov 05 '16 at 16:49
  • I didn't find any code or documentation of how to serve a directory – Drarig29 Nov 05 '16 at 16:52
  • We were talking about serving files i thought. Now suddenly you start talking about serving a directory. What do you mean by that? – greenapps Nov 05 '16 at 16:53
  • Maybe i'm expressing myself badly. Do you see the two apps I speak about in my question? I'd like to reproduce their behavior with the home/root directory thing (just look at the screenshots in Google Play) – Drarig29 Nov 05 '16 at 16:55
  • No i cannot see them as i have to log in first. – greenapps Nov 05 '16 at 16:56
  • Are you busy? Can we go to stackoverflow's chat? Maybe it'll be better? – Drarig29 Nov 05 '16 at 16:57
  • `I found this answer, but this is not what I want. It consists in returning the content of an .html file in a Response object with the serve() method.`. Well why does that not suit you? It constructs a file path from a directory and a filename. After that it serves the file from file path. You can take the root directory you want and the file name will be in parameter uri. – greenapps Nov 05 '16 at 16:59
  • No chat. I hate chat. – greenapps Nov 05 '16 at 17:01
  • ok. sorry. it doesn't load the images if there is a relative link to a local directory, for example an image, this image is not loaded – Drarig29 Nov 05 '16 at 17:04
  • while if I use one of the two apps I spoke about in my question, the images are loaded, and even javascript scripts! – Drarig29 Nov 05 '16 at 17:05
  • Of course that image will be requested from the browser too. So nanohttpd will receive the request. Look at the url parameter. It will contain the relative path of the image. Then serve the image file. You need different code of course to serve an image as you cannot use `readLine()`. – greenapps Nov 05 '16 at 17:07
  • Ok, and are there other types of file I should interest me? (like images) – Drarig29 Nov 05 '16 at 17:09
  • Like images? Weren't we already talking about loading of images!???? – greenapps Nov 05 '16 at 17:10
  • Sorry, this is not what I wanted to say. You see images are "special" because you can't use readLine(). Are there other types of file I should interest me because we can't use readLine(). Maybe special things that I don't know anything about. More clearly, if I just add code to return text and to return images, will my website entirely work? – Drarig29 Nov 05 '16 at 17:13
  • What do you want to return more? What kind of other files would be requested from the browser? – greenapps Nov 05 '16 at 17:14
  • I don't know ^^ Indeed, I think it's a stupid question. Thanks for the help ;) – Drarig29 Nov 05 '16 at 17:16
  • If you have the code to serve an image file then you can serve any file with it. Also the html files and the css files. So you could do away with the readLine stuff all togeter. – greenapps Nov 05 '16 at 17:18
  • Perfect. Thank you! – Drarig29 Nov 05 '16 at 17:20

3 Answers3

2

I have been successfull in serving a folder of files via the following code... This is my Response method inside my Android Web Server class -->

public Response serve(IHTTPSession session) {
    String uri=session.getUri();
    String msg = "<html><body><h1>Hello server</h1>\n";

    File [] arrayfile;

    int i=0;

    try{
        session.parseBody(new HashMap<String, String>());
    }catch (ResponseException | IOException r){
        r.printStackTrace();
    }


    Map<String, String> parms = session.getParms();
    if (parms.get("username") == null) {
        msg += "<form action='?' method='get'>\n  <p>Your name: <input type='text' name='username'></p>\n" + "</form>\n";
    } else {
        msg += "<p>Hello, " + parms.get("username") + "!</p>";
    }
    msg += "<br><br><a href='/Open_rap'>Open Image of Lionel Messi</a><br><br>";
    msg += "<br><br><a href='/files'>Browse Files</a><br><br>";
    msg += "<br><br><a href='/getmethod'>GET METHOD OPERATION</a><br><br>";
    msg += "<br><br><a href='/postmethod'>POST METHOD OPERATION</a><br><br>";
    msg += "<br><br><a href='/jquery'>JQUERY OPERATION</a><br><br>";
    if(uri.equals("/hello")){
            String response="Hello World";
            return  newFixedLengthResponse(response);
    }
    else if(uri.equals("/getmethod")){
        String html="<html><head><h1>Welcome to the Form</h1><head/><body>";

        if(parms.get("name")==null){
            html +="<form action='' method='get'> \n " +
                    "<p>Enter Your Name:</p> <input type='text' name='name'>" +
                    "</form>" +
                    "</body>";
        }
        else{
            html +="<p>Hello Mr. "+ parms.get("name") +"</p>"+
                    "</body> ";
        }

        html +="</html>";
        return newFixedLengthResponse(html);

    }
    else if(uri.equals("/postmethod")){
        String html="<html><head><h1>Welcome to the Form</h1><head/><body>";
        Map<String, String> files = new HashMap<String, String>();
        Method method = session.getMethod();
        String postParameter="";


        html +="<form action='' method='post'> \n " +
                "<p>Enter Your Name:</p> <input type='text' name='name'>" +
                "</form>";

        if (Method.POST.equals(method) || Method.PUT.equals(method)) {
            try {
                session.parseBody(files);
            } catch (IOException ioe) {
                try {
                   // return newFixedLengthResponse(Response.Status.INTERNAL_ERROR, MIME_PLAINTEXT, "SERVER INTERNAL ERROR: IOException: " + ioe.getMessage());
                } catch (Exception e) {
                    e.printStackTrace();
                    Log.d("Exception", e.getMessage());
                }
            } catch (ResponseException re) {
                try {
                   // return newFixedLengthResponse(re.getStatus(), MIME_PLAINTEXT, re.getMessage());
                } catch (Exception e) {
                    e.printStackTrace();
                    Log.d("Exception", re.getMessage());
                }
            }
        }
        html +="</body></html>";
        String postBody = session.getQueryParameterString();
        postParameter = session.getParms().get("name");
        Log.d("Postbody",postBody+"\n"+postParameter);
        if(postParameter!=null){
            String html1="<html><head><h1>"+ postParameter +"</h1><head></html>";
            return newFixedLengthResponse(html1);
        }
        return newFixedLengthResponse(Response.Status.OK,"text/html",html);
    }

    else if(uri.equals("/Open_rap")){

        File root= Environment.getExternalStorageDirectory();
        FileInputStream fis = null;
        File file = new File(root.getAbsolutePath() + "/www/messi.jpg");
        try{
            if(file.exists())
            {
                fis = new FileInputStream(file);

            }
            else
                Log.d("FOF :", "File Not exists:");
        }catch (FileNotFoundException e)
        {
            e.printStackTrace();
        }


        return newFixedLengthResponse(Response.Status.OK,"image/jpeg",fis, file.length() );
    }

    else if(uri.equals("/files")) {
        File root = Environment.getExternalStorageDirectory();

        FileInputStream fis = null;
        File file = new File(root.getAbsolutePath() + "/www/files/");
        arrayfile = file.listFiles();
        String html = "<html><body><h1>List Of All Files</h1>";
        for (i = 0; i < arrayfile.length; i++) {
            Log.d("Files", "FileName:" + arrayfile[i].getName());
            html += "<a href='/www/files/" + arrayfile[i].getName() + "' >" + arrayfile[i].getName() + "</a><br><br>";

        }
        html += "</body></html>";

        return newFixedLengthResponse(html);
    }


    else if(uri.equals("/jquery")){
        String address="http://"+MainActivity.ipaddress+":8080/jquery-3.3.1.min.js";
        Log.d("IP",address);
        String s="<html>\n" +
                "<head>\n" +
            //    "<script src=\"https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js\"></script>\n" +
             //   "<script src='file:///android_asset/js/jquery-3.3.1.min.js' type='text/javascript'></script>\n" +
               "<script src='"+address+"'></script>\n" +
                "<script>\n" +
                "$(document).ready(function(){\n" +
                "    $(\"button\").click(function(){\n" +
                "        $(\"p\").toggle();\n" +
                "    });\n" +
                "});\n" +
                "</script>\n" +
                "</head>\n" +
                "<body>\n" +
                "\n" +
                "<h2>This is a heading</h2>\n" +
                "\n" +
                "<button>Click me to hide paragraphs</button>\n" +
                "<p>This is a paragraph.</p>\n" +
                "<p>This is another paragraph.</p>\n" +
                "\n" +
                "\n" +
                "</body>\n" +
                "</html>\n";
        return newFixedLengthResponse(s);

    }
    else if(uri.equals("/jquery-3.3.1.min.js")){

        File root= Environment.getExternalStorageDirectory();
        FileInputStream fis = null;
        File file = new File(root.getAbsolutePath() + "/www/resources/jquery-3.3.1.min.js");
        Log.d("Jquery","hello");
        try{
            if(file.exists())
            {
                fis = new FileInputStream(file);

            }
            else
                Log.d("FOF :", "File Not exists:");
        }catch (FileNotFoundException e)
        {
            e.printStackTrace();
        }


        return newFixedLengthResponse(Response.Status.OK,"application/javascript",fis, file.length() );
    }

    else if(uri.contains(".")){

        String[] split=uri.split("/");
        String s="";
        for (i=0;i<split.length;i++){
            Log.d("String",""+split[i]+""+i);
            s=s+"/"+split[i];
        }
        String x=s.substring(1,s.length());
        Log.d("String2",s);
        Log.d("String2",x+"  "+x.length());
        String y = NanoHTTPD.getMimeTypeForFile(x);
        Log.d("MIME-TYPE",y);
        File root= Environment.getExternalStorageDirectory();
        FileInputStream fis = null;
        //File file = new File(root.getAbsolutePath() + "/"+split[1]+"/"+split[2]+"/"+split[3]);
        File file=new File(root.getAbsolutePath()+x);
        try{
            if(file.exists())
            {
                fis = new FileInputStream(file);

            }
            else
                Log.d("FOF :", "File Not exists:");
        }catch (FileNotFoundException e)
        {
            e.printStackTrace();
        }

        return newFixedLengthResponse(Response.Status.OK,y,fis, file.length() );

    }

    else {
        return newFixedLengthResponse(msg + "</body></html>\n");
    }

}

As you can see, the part where uri.contains(.)
this part of code is where I implement the folder using a root file object and file input stream My files are kept inside the internal storage of my android device /www/files Ping me if you have any issue.

Shan Singh
  • 104
  • 1
  • 6
  • Ok so you are manually returning file input streams, I was just searching for a "magical" solution where there is a function that we can use to set a root directory... But I just have to enumerate all the files within my directory and I do the work! Thanks :D – Drarig29 May 31 '18 at 07:31
  • 1
    @Drarig29 yes exactly, even I was wishing for some magical method that would help and honestly it took me a whole afternoon to figure out how to access files properly on the webserver, keeping in mind Nanohttpd creates a totally different environment which is completely different from the ones we use on our PC's. *pheewww* – Shan Singh May 31 '18 at 08:20
  • Can you share any idea how can I access storage directory file list. There is an app "kWS" in playstore, what I'm looking for is source code. – Koushik Mondal Jun 01 '20 at 19:48
2

You can use google/webview-local-server

Amir Khorsandi
  • 3,542
  • 1
  • 34
  • 38
2

I am using nanohttpd to serve files here is my working code that i used

@Override
public Response serve(IHTTPSession session) {
    String msg = "<html><body><h1>Hello server</h1></body></html>\n";
    String msgUnauthorized = "<html><body><h1>Unauthorized</h1></body></html>\n";
    Method method = session.getMethod();
    String uri = session.getUri();
    Map<String, String> files = new HashMap<>();

    String Endpoint = session.getUri();
    if (Endpoint.equals("/")) {

        String answer = "";
        try {
            // Open file from SD Card
            File root = Environment.getExternalStorageDirectory().getAbsoluteFile();
            FileReader index = new FileReader(root +
                    "/www/openrap/index.html");
            BufferedReader reader = new BufferedReader(index);
            String line = "";
            while ((line = reader.readLine()) != null) {
                answer += line;
            }
            reader.close();
        } catch (IOException ioe) {
            Log.w("Httpd", ioe.toString());
        }

        return newFixedLengthResponse(answer);
    }
sanjay
  • 695
  • 11
  • 22