You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用NanoHttpd提供指定多文件服务并生成可访问URL

Got it, let's tackle this problem step by step. You already have a basic NanoHttpd setup serving a single file, and now you want to expand it to serve multiple specific files from the SD card without generating directory listings. Here's how to make it work:

1. Create a Custom NanoHttpd Server Class

We'll build a server that maintains a mapping between URL path fragments and your selected files. This way, only the files you specify are accessible via the network.

import fi.iki.elonen.NanoHTTPD;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

public class MultiFileServer extends NanoHTTPD {
    private final Map<String, File> fileMapping;

    // Constructor: Accept array of SD card file paths directly
    public MultiFileServer(int port, String[] sdCardFilePaths) throws IOException {
        super(port);
        fileMapping = new HashMap<>();
        
        // Populate the mapping: Use filename (or relative path) as the URL endpoint
        for (String filePath : sdCardFilePaths) {
            File targetFile = new File(filePath);
            if (targetFile.exists() && targetFile.isFile()) {
                // Option 1: Use just the filename (e.g., "/vacation.jpg")
                String urlPath = "/" + targetFile.getName();
                
                // Option 2: Use relative path from SD root to avoid duplicate filenames (e.g., "/Photos/vacation.jpg")
                // String sdRoot = Environment.getExternalStorageDirectory().getPath();
                // String urlPath = "/" + filePath.replace(sdRoot, "").replace("//", "/");
                
                fileMapping.put(urlPath, targetFile);
            }
        }
    }

    @Override
    public Response serve(IHTTPSession session) {
        String requestedUri = session.getUri();
        
        // Check if the requested URI matches any of our served files
        if (fileMapping.containsKey(requestedUri)) {
            File fileToServe = fileMapping.get(requestedUri);
            try {
                // Auto-detect MIME type for the file
                String mimeType = NanoHTTPD.getMimeTypeForFile(fileToServe.getName());
                return newChunkedResponse(Response.Status.OK, mimeType, new FileInputStream(fileToServe));
            } catch (IOException e) {
                return newFixedLengthResponse(Response.Status.INTERNAL_ERROR, "text/plain", "Failed to read file: " + e.getMessage());
            }
        }
        
        // Return 404 if the requested file isn't in our whitelist
        return newFixedLengthResponse(Response.Status.NOT_FOUND, "text/plain", "This file is not served by this server");
    }
}
2. Initialize the Server with Your Selected File Paths

Once you've picked multiple files from the SD card (via a file picker, for example), pass their paths directly to the server constructor:

// Example: Array of paths to files you selected from the SD card
String[] selectedSdFiles = {
    "/sdcard/Documents/project-report.pdf",
    "/sdcard/Photos/summer-trip.jpg",
    "/sdcard/Music/background-track.mp3"
};

try {
    // Start the server on port 8080 (choose any available port)
    MultiFileServer fileServer = new MultiFileServer(8080, selectedSdFiles);
    fileServer.start();
    System.out.println("Multi-file server is running!");
} catch (IOException e) {
    e.printStackTrace();
}
3. Generate Accessible URLs for Each File

To get shareable URLs, you'll need your device's local IP address plus the server port and the mapped URL path for each file. Here's a helper to generate these URLs:

import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.Enumeration;

// Helper to get your device's local network IP (for access from other devices on the same network)
private static String getLocalIp() {
    try {
        for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) {
            NetworkInterface intf = en.nextElement();
            for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) {
                InetAddress inetAddr = enumIpAddr.nextElement();
                if (!inetAddr.isLoopbackAddress() && inetAddr.isSiteLocalAddress()) {
                    return inetAddr.getHostAddress();
                }
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    return "127.0.0.1"; // Fallback to localhost if IP detection fails
}

// Generate and print URLs for all served files
public void printAccessUrls(MultiFileServer server) {
    String serverIp = getLocalIp();
    int port = server.getListeningPort();
    
    System.out.println("\nAccessible URLs:");
    for (Map.Entry<String, File> entry : server.fileMapping.entrySet()) {
        String fullUrl = "http://" + serverIp + ":" + port + entry.getKey();
        System.out.println(entry.getValue().getName() + " → " + fullUrl);
    }
}
Key Considerations
  • Duplicate Filenames: If you have files with the same name in different folders, use the relative path option (Option 2 in the server constructor) to avoid URL conflicts.
  • Permissions: On Android, ensure you have the necessary storage permissions. For Android 10+, use scoped storage or request MANAGE_EXTERNAL_STORAGE to access SD card files.
  • Security: This setup only serves the files you explicitly select, so you don't risk exposing your entire SD card to the network.

内容的提问来源于stack exchange,提问作者arjun

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 10:00:47