在本地主机上使用 nanohttpd 作为服务器,如何在整个目录中提供静态 HTML 代码?

我无法让 nanohttpd 工作。似乎无法www在应用程序的根目录中找到该目录。


我的代码在https://github.com/tlkahn/neonx


我在 MainActivity.java 的代码:


@Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        BottomNavigationView navView = findViewById(R.id.nav_view);

        mWebView = findViewById(R.id.webkit);

        navView.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);

        WebSettings webSettings = mWebView.getSettings();

        webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);

        webSettings.setDomStorageEnabled(true);

        mWebView.getSettings().setLoadsImagesAutomatically(true);

        mWebView.getSettings().setJavaScriptEnabled(true);

        mWebView.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);

        mWebView.setWebViewClient(new WebViewClient() {

            @Override

            public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {

                return false;

            }

        });

        if (!haveNetworkConnection()) {

            new AlertDialog.Builder(this)

                .setTitle("You are not connected to internet.")

                .setMessage("Are you sure you want to exit?")

                .setPositiveButton("Yes", new DialogInterface.OnClickListener() {

                    @Override

                    public void onClick(DialogInterface dialog, int which) {

                        finishAffinity();

                        System.exit(0);

                    }

                }).setNegativeButton("No", null).show();

        }

        startLocalServer(3000, "www", true, true );

    }



当我尝试访问时localhost:3000,出现错误:给定路径不是目录。错误似乎来自这一行: https: //git.io/fjS3f


我猜我初始化 rootDir 的方式是错误的(这一行:https: //git.io/fjS3v)。但是我怎样才能使这项工作呢?我的意思是服务整个目录,这意味着所有 CSS/JS/hypyerlinks 应该工作,一旦 nanohttpd 开始服务......


智慧大石
浏览 202回答 2
2回答

吃鸡游戏

问题是您无法像访问本地文件一样访问 assets 文件夹中的文件。您必须扩展 NanoHTTPD 并覆盖 serve(IHTTPSession) 才能提供资产。这是 Kotlin 中的示例。如果您看不懂,请告诉我,我会将其移植到 Java。class FileServer(private val context: Context, port: Int) : NanoHTTPD(port) {override fun serve(session: IHTTPSession): Response {    val uri = session.uri.removePrefix("/").ifEmpty { "index.html" }    println("Loading $uri")    try {        val mime = when (uri.substringAfterLast(".")) {            "ico" -> "image/x-icon"            "css" -> "text/css"            "htm" -> "text/html"            "html" -> "text/html"            else -> "application/javascript"        }        return NanoHTTPD.newChunkedResponse(            Response.Status.OK,            mime,            context.assets.open("www/$uri") // prefix with www because your files are not in the root folder in assets        )    } catch (e: Exception) {        val message = "Failed to load asset $uri because $e"        println(message)        e.printStackTrace()        return NanoHTTPD.newFixedLengthResponse(message)    }}

慕后森

输出:日志猫:2019-08-05 15:21:53.838 10650-10650/com.neonxorg.neonx E/MainActivity: -------Assets List-----2019-08-05 15:21:53.838 10650-10650/com.neonxorg.neonx E/MainActivity: asset-manifest.json2019-08-05 15:21:53.838 10650-10650/com.neonxorg.neonx E/MainActivity: favicon.ico2019-08-05 15:21:53.838 10650-10650/com.neonxorg.neonx E/MainActivity: index.html2019-08-05 15:21:53.838 10650-10650/com.neonxorg.neonx E/MainActivity: manifest.json2019-08-05 15:21:53.838 10650-10650/com.neonxorg.neonx E/MainActivity: precache-manifest.81af63d07b6dd6ae8e331187c522b020.js2019-08-05 15:21:53.838 10650-10650/com.neonxorg.neonx E/MainActivity: service-worker.js2019-08-05 15:21:53.838 10650-10650/com.neonxorg.neonx E/MainActivity: static2019-08-05 15:21:53.842 10650-10650/com.neonxorg.neonx E/MainActivity: copyFolderFromAssets rootDirFullPath-www targetDirFullPath-/storage/emulated/0/Android/data/com.neonxorg.neonx/cache/www2019-08-05 15:21:53.865 10650-10650/com.neonxorg.neonx E/MainActivity: copyFolderFromAssets rootDirFullPath-www/static targetDirFullPath-/storage/emulated/0/Android/data/com.neonxorg.neonx/cache/www/static2019-08-05 15:21:53.867 10650-10650/com.neonxorg.neonx E/MainActivity: copyFolderFromAssets rootDirFullPath-www/static/css targetDirFullPath-/storage/emulated/0/Android/data/com.neonxorg.neonx/cache/www/static/css2019-08-05 15:21:53.922 10650-10650/com.neonxorg.neonx E/MainActivity: copyFolderFromAssets rootDirFullPath-www/static/js targetDirFullPath-/storage/emulated/0/Android/data/com.neonxorg.neonx/cache/www/static/js2019-08-05 15:21:54.352 10650-10650/com.neonxorg.neonx E/MainActivity: copyFolderFromAssets rootDirFullPath-www/static/media targetDirFullPath-/storage/emulated/0/Android/data/com.neonxorg.neonx/cache/www/static/media2019-08-05 15:21:54.526 10650-10650/com.neonxorg.neonx E/MainActivity: -------Root File List-----2019-08-05 15:21:54.528 10650-10650/com.neonxorg.neonx E/File: /storage/emulated/0/Android/data/com.neonxorg.neonx/cache/www/precache-manifest.81af63d07b6dd6ae8e331187c522b020.js2019-08-05 15:21:54.528 10650-10650/com.neonxorg.neonx E/File: /storage/emulated/0/Android/data/com.neonxorg.neonx/cache/www/service-worker.js2019-08-05 15:21:54.528 10650-10650/com.neonxorg.neonx E/File: /storage/emulated/0/Android/data/com.neonxorg.neonx/cache/www/static2019-08-05 15:21:54.528 10650-10650/com.neonxorg.neonx E/File: /storage/emulated/0/Android/data/com.neonxorg.neonx/cache/www/favicon.ico2019-08-05 15:21:54.528 10650-10650/com.neonxorg.neonx E/File: /storage/emulated/0/Android/data/com.neonxorg.neonx/cache/www/manifest.json2019-08-05 15:21:54.528 10650-10650/com.neonxorg.neonx E/File: /storage/emulated/0/Android/data/com.neonxorg.neonx/cache/www/asset-manifest.json2019-08-05 15:21:54.528 10650-10650/com.neonxorg.neonx E/File: /storage/emulated/0/Android/data/com.neonxorg.neonx/cache/www/index.html2019-08-05 15:21:54.704 10650-10650/com.neonxorg.neonx E/MainActivity: Connected : Please access! http://192.168.1.2:3000 From a web browser代码:public final String TAG = getClass().getSimpleName();public void startLocalServer(int port, String root, Boolean localhost, Boolean keepAlive) {        try {            String[] filePathList = (getAssets().list("www"));            Log.e(TAG,"-------Assets List-----");            for (String s : filePathList) {                Log.e(TAG, s);            }            File externalCache = getExternalCacheDir();            if (externalCache != null) {                String path = externalCache.getAbsolutePath() + "/" + root;                copyFolderFromAssets(getApplicationContext(), "www", path);                File www_root = new File(path);                Log.e(TAG,"-------Root File List-----");                for (File f : www_root.listFiles()) {                    Log.e("File ", f.getAbsolutePath());                }                server = new WebServer("localhost", port, www_root.getCanonicalFile());                server.start();                printIp();            }        } catch (IOException e) {            Log.e(TAG, Log.getStackTraceString(e));        }    }    public void copyFolderFromAssets(Context context, String rootDirFullPath, String targetDirFullPath) {        Log.e(TAG,"copyFolderFromAssets " + "rootDirFullPath-" + rootDirFullPath + " targetDirFullPath-" + targetDirFullPath);        File file = new File(targetDirFullPath);        if (!file.exists()) {            new File(targetDirFullPath).mkdirs();        }        try {            String[] listFiles = context.getAssets().list(rootDirFullPath);// 遍历该目录下的文件和文件夹            for (String string : listFiles) {// 看起子目录是文件还是文件夹,这里只好用.做区分了                if (isFileByName(string)) {// 文件                    copyFileFromAssets(context, rootDirFullPath + "/" + string, targetDirFullPath + "/" + string);                } else {// 文件夹                    String childRootDirFullPath = rootDirFullPath + "/" + string;                    String childTargetDirFullPath = targetDirFullPath + "/" + string;                    new File(childTargetDirFullPath).mkdirs();                    copyFolderFromAssets(context, childRootDirFullPath, childTargetDirFullPath);                }            }        } catch (IOException e) {            Log.e(TAG, Log.getStackTraceString(e));        }    }    public void copyFileFromAssets(Context context, String assetsFilePath, String targetFileFullPath) {        InputStream assestsFileInputStream;        try {            assestsFileInputStream = context.getAssets().open(assetsFilePath);            FileOutputStream fOS = new FileOutputStream(new File(targetFileFullPath));            int length = -1;            byte[] buf = new byte[1024];            while ((length = assestsFileInputStream.read(buf)) != -1) {                fOS.write(buf, 0, length);            }            fOS.flush();        } catch (IOException e) {            Log.e(TAG, Log.getStackTraceString(e));        }    }    private boolean isFileByName(String str) {        return str.contains(".");    }    private void printIp() {        WifiManager wifiManager = (WifiManager) getApplicationContext().getSystemService(WIFI_SERVICE);        int ipAddress = wifiManager.getConnectionInfo().getIpAddress();        final String formatedIpAddress = String.format("%d.%d.%d.%d", (ipAddress & 0xff), (ipAddress >> 8 & 0xff),                (ipAddress >> 16 & 0xff), (ipAddress >> 24 & 0xff));        Log.e(TAG,"Connected : " + "Please access! http://" + formatedIpAddress + ":" + server.getListeningPort() + " From a web browser");    }给定路径不是目录。当 nanphttpd 无法定位数据时,它会给出此错误。为什么你没有得到实际的错误在你正在使用的catch 块中,copyFolderFromAssets由于仅显示选定的应用程序过滤器,它可能不会显示在你的 LogCat 上copyFileFromAssetse.printStackTrace()为了打印错误,您需要使用以下内容:Log.e(TAG, Log.getStackTraceString(e));我用 Log.e 语句替换了所有 System.out 和 e.printStackTrace。应用程序很可能无法将内容从 www 目录复制到目标目录。我将目标目录更改为缓存目录,它在我的设备上运行。(见下文):File externalCache = getExternalCacheDir();if (externalCache != null) {    String path = externalCache.getAbsolutePath() + "/" + root;    File www_root = new File(path);    copyFolderFromAssets(getApplicationContext(), "www", path);    Log.e(TAG,"-------Root File List-----");    for (File f : www_root.listFiles()) {        Log.e("File ", f.getAbsolutePath());    }    server = new WebServer("localhost", port, www_root.getCanonicalFile());    server.start();    printIp();}边注:static除非或除非您想将它们复制到实用程序类中,否则无需在这些函数中使用关键字
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java