How to download two or multiple files at a time in Android using NanoHTTPD?
Asked Answered
R

2

9

I use NanoHTTPD as web server in my Android app.

I pass two file names from client browser to NanoHTTPD server, and I hope to download the two files at a time, but the following code only download the file1, and the file2 isn't downloaded.

How to download two or multiple files at a time?

public class MyWebServer extends NanoHTTPD
{

    private final String rootDir;

    public MyWebServer(int port, String rootDir)
    {
        super("192.168.1.4", port);
        this.rootDir = rootDir;
    }

    @Override
    public Response serve(IHTTPSession session)
    {       
        Map<String, String> parms = session.getParms();

        String filename1=GetFilename(parms);
        String filename2=GetFilename(parms);

        File file1 = new File(rootDir + filename1);
        File file2 = new File(rootDir + filename2);

        return downloadFile(file1);
        return downloadFile(file2);
    }


    private Response downloadFile(File file)
    {
        FileInputStream fis = null;
        try
        {
            fis = new FileInputStream(file);
        } catch (FileNotFoundException ex)
        {
            Logger.getLogger(MyWebServer.class.getName()).log(Level.SEVERE, null, ex);
        }
        return newFixedLengthResponse(Response.Status.OK, "application/octet-stream", fis, file.getTotalSpace());
    }



    @Override
    public Response newFixedLengthResponse(IStatus status, String mimeType, String message)
    {
        Response response = super.newFixedLengthResponse(status, mimeType, message);
        response.addHeader("Accept-Ranges", "bytes");
        return response;
    }


}
Romberg answered 15/2, 2017 at 3:29 Comment(8)
call 2 times MyWebServer with filename1 and filename2Hightower
Thanks! but I hope to call 1 time MyWebServer and download two filesRomberg
return downloadFile(file1); because of this return downloadFile(file2); it will never get calledHightower
Thanks! How to download two or multiple files at a time in Android using NanoHTTPD?Romberg
Possible duplicate of How to download multiple files in Android using NanoHTTPD web server?Vanover
Why do you think you can ask same question twice? Do you think that it is more important than any other question? Why it would be? You are not allowed to ask it again even if you didn't get answer to previous question.Vanover
I have deleted old duplicate question. This question is more accurateRomberg
You can pass an array to download task with files names :)Fairman
S
4

Below NanoHTTPD constructor creates an async task when you call super(..) in the MyWebServer constructor.

public NanoHTTPD(String hostname, int port) {
        this.hostname = hostname;
        this.myPort = port;
        setTempFileManagerFactory(new DefaultTempFileManagerFactory());
        setAsyncRunner(new DefaultAsyncRunner());

        // creates a default handler that redirects to deprecated serve();
        this.httpHandler = new IHandler<IHTTPSession, Response>() {

            @Override
            public Response handle(IHTTPSession input) {
                return NanoHTTPD.this.serve(input);
            }
        };
    }

So the answer must be to have one downloadFile() for each operation. That is to say you should call new MyWebServer() to start each download task.

@Override
    public Response serve(IHTTPSession session)
    {       
        Map<String, String> parms = session.getParms();

        String filename=GetFilename(parms);

        File file = new File(rootDir + filename);

        return downloadFile(file);
    }

EDIT:

By using 2 instance of MyWebServer class, u can listen to client requests for each of 2 params. (I didn't try this but it must work and I recommend you should send multiple requests on the client side and one webserver instance on the server side).

public class MyWebServer extends NanoHTTPD
{

    private final String rootDir;
    private final int param_type = 1; //default 1

    public MyWebServer(int port, String rootDir, int param)
    {
        super("192.168.1.4", port);
        this.rootDir = rootDir;
        this.param_type = param;
    }

    @Override
    public Response serve(IHTTPSession session)
    {       
        Map<String, String> parms = session.getParms();
        File file;

        if (param_type == 1){
             String filename=parms.get("param1");
             file = new File(rootDir + filename);
        }else if(param_type == 2){ 
             String filename=parms.get("param2");
             file = new File(rootDir + filename);
        }


        return downloadFile(file);
    }


    private Response downloadFile(File file)
    {
        FileInputStream fis = null;
        try
        {
            fis = new FileInputStream(file);
        } catch (FileNotFoundException ex)
        {
            Logger.getLogger(MyWebServer.class.getName()).log(Level.SEVERE, null, ex);
        }
        return newFixedLengthResponse(Response.Status.OK, "application/octet-stream", fis, file.getTotalSpace());
    }



    @Override
    public Response newFixedLengthResponse(IStatus status, String mimeType, String message)
    {
        Response response = super.newFixedLengthResponse(status, mimeType, message);
        response.addHeader("Accept-Ranges", "bytes");
        return response;
    }


}

In MainActivity.java

 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        MyWebServer server1 = new MyWebServer(port, rootDir, 1);
        MyWebServer server2 = new MyWebServer(port, rootDir, 2);

        server1.start();
        server2.start();

    }
Spruill answered 22/2, 2017 at 22:45 Comment(11)
Thanks! Normally, I create one instance of MyWebServer to listen to client side request, now client side pass two filenames and request to download. How can I create New MyWebserver() to send two files to client side?Romberg
How do you make client side requests?Spruill
I use POST method to send two filename to server sideRomberg
Have you tried sending request with for loop like this: https://mcmap.net/q/711754/-loop-through-a-post-arraySpruill
I believe you can handle this in the client side. If the client sends requests in the loop one by one then you dont need to implement to response return in your NANOHTTPD. It will retrun a response whenever it gets a request from client.Spruill
Thanks! In NANOHTTPD, you can't do " return downloadFile(file1); return downloadFile(file2); " because "return downloadFile(file2)" never be lanuchedRomberg
Sure. So you can't return 2 response at the same time. Either send them in a loop or merge files into one stream and manage it in the client even I don't recommend this.Spruill
Thanks! Could you give some sample code about "So the answer must be to have one downloadFile() for each operation. That is to say you should call new MyWebServer() to start each download task."Romberg
Thanks! but I don't think your code is good. If I need download 10 files, will you create 10 instance ?Romberg
And more, if client side send a request, will the 10 instance handle the request simultaneously ?Romberg
I agree this is ugly solution u should handle on the client sideSpruill
M
-1

In Java, when you want a function to return multiple values, you must embed those values in an object you return. So you need to define a class (for example: ReturnDownlowds) which could have two objects:

public class ReturnDownlowds {
    private File downloadFile1;
    private File downloadFile2;

// add other fields, constructor and accessors

}

And in your Response server method you need to recall a sample of this class like this:

return new ReturnDownlowds(downloadFile1, downloadFile2) ;

I hope this would be a little help.

Mesic answered 19/2, 2017 at 21:34 Comment(1)
Thanks! But Web server is stateless!Romberg

© 2022 - 2024 — McMap. All rights reserved.