19

我使用 NanoHTTPD 编写了一个小型 Android 服务器。它可以很好地提供 HTML 文件(位于 sdcard/www/index.html 的网页)。谁能帮我找出如何使用 NanoHTTPD 提供音频或视频文件而不是 html 页面?如果这个问题看起来很愚蠢,请原谅我,因为我是 HTTP 新手!这是我的服务器端代码(我已将网页路径替换为音频文件的路径):

package com.example.zserver;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.Map;

import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;

public class MainActivity extends Activity {

    private WebServer server;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        server = new WebServer();
        try {
            server.start();
        } catch(IOException ioe) {
            Log.w("Httpd", "The server could not start.");
        }
        Log.w("Httpd", "Web server initialized.");

    }
    @Override
    public void onDestroy()
    {
        super.onDestroy();
        if (server != null)
            server.stop();
    }

    private class WebServer extends NanoHTTPD {

        public WebServer()
        {
            super(8080);
        }

        @Override
        public Response serve(String uri, Method method, 
                              Map<String, String> header,
                              Map<String, String> parameters,
                              Map<String, String> files) {
            String answer = "";
            try {
                // Opening file from SD Card
                File root = Environment.getExternalStorageDirectory();
                FileReader index = new FileReader(root.getAbsolutePath() +
                        "/www/music.mp3");              
                BufferedReader reader = new BufferedReader(index);
                String line = "";
                while ((line = reader.readLine()) != null) {
                    answer += line;
                }

            } catch(IOException ioe) {
                Log.w("Httpd", ioe.toString());
            }


            return new NanoHTTPD.Response(answer);
        }
    }

}

我在我的代码中包含了必要的使用权限:

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

任何帮助,将不胜感激。提前致谢!

编辑,添加权限:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

EDIT1:读取和写入缓冲区的规范方式:

int read;
        int n=1;
        while((read = dis.read(mybytearray)) != -1){
            dos.write(mybytearray, 0, read);}
4

3 回答 3

46

首先,您需要确保在提供媒体文件时正确设置 mimetype。

其次,使用 . 逐行读取 MP3 文件不会太远FileReader,相反,您应该为 NanoHTTPD 提供InputStream.

下面是您的代码的工作修改版本,它提供 MP3 文件。通过将 mimetype 设置为audio/mpeg您,让浏览器决定如何处理此内容。例如,在 Chrome 中,集成的音乐播放器会启动并播放文件。

public class StackOverflowMp3Server extends NanoHTTPD {

    public StackOverflowMp3Server() {
         super(8089);
    }

    @Override
    public Response serve(String uri, Method method,
        Map<String, String> header, Map<String, String> parameters,
        Map<String, String> files) {
    String answer = "";

    FileInputStream fis = null;
    try {
        fis = new FileInputStream(Environment.getExternalStorageDirectory()
                + "/music/musicfile.mp3");
    } catch (FileNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return new NanoHTTPD.Response(Status.OK, "audio/mpeg", fis);
  }
}

编辑:很多人一直在问如何使用范围请求使音频文件可搜索,我将在下面演示

为了使音频文件可搜索,使用范围请求使 HTTP 客户端能够以块的形式检索部分音频文件。确保您使用 PARTIAL_CONTENT 响应状态 (HTTP 206) 提供文件。在 NanoHTTPD 的示例代码中可以找到一个示例实现: SimpleWebserver.java

在我的实现中,我没有直接在 serve 方法中返回 NanoHTTPD 响应,而是创建了另一个名为“servefile”的方法,我将其用作处理范围请求的响应,如下所示。这段代码是我上面链接的 SimpleWebServer.java 的修改实现。

  @Override
  public Response serve(String uri, Method method,
        Map<String, String> header, Map<String, String> parameters,
        Map<String, String> files) {

    File f = new File(Environment.getExternalStorageDirectory()
            + "/music/musicfile.mp3");      
    String mimeType =  "audio/mpeg";

    return serveFile(uri, header, f, mimeType);
}
//Announce that the file server accepts partial content requests
private Response createResponse(Response.Status status, String mimeType,
        InputStream message) {
    Response res = new Response(status, mimeType, message);
    res.addHeader("Accept-Ranges", "bytes");
    return res;
}

/**
 * Serves file from homeDir and its' subdirectories (only). Uses only URI,
 * ignores all headers and HTTP parameters.
 */
private Response serveFile(String uri, Map<String, String> header,
        File file, String mime) {
    Response res;
    try {
        // Calculate etag
        String etag = Integer.toHexString((file.getAbsolutePath()
                + file.lastModified() + "" + file.length()).hashCode());

        // Support (simple) skipping:
        long startFrom = 0;
        long endAt = -1;
        String range = header.get("range");
        if (range != null) {
            if (range.startsWith("bytes=")) {
                range = range.substring("bytes=".length());
                int minus = range.indexOf('-');
                try {
                    if (minus > 0) {
                        startFrom = Long.parseLong(range
                                .substring(0, minus));
                        endAt = Long.parseLong(range.substring(minus + 1));
                    }
                } catch (NumberFormatException ignored) {
                }
            }
        }

        // Change return code and add Content-Range header when skipping is
        // requested
        long fileLen = file.length();
        if (range != null && startFrom >= 0) {
            if (startFrom >= fileLen) {
                res = createResponse(Response.Status.RANGE_NOT_SATISFIABLE,
                        NanoHTTPD.MIME_PLAINTEXT, "");
                res.addHeader("Content-Range", "bytes 0-0/" + fileLen);
                res.addHeader("ETag", etag);
            } else {
                if (endAt < 0) {
                    endAt = fileLen - 1;
                }
                long newLen = endAt - startFrom + 1;
                if (newLen < 0) {
                    newLen = 0;
                }

                final long dataLen = newLen;
                FileInputStream fis = new FileInputStream(file) {
                    @Override
                    public int available() throws IOException {
                        return (int) dataLen;
                    }
                };
                fis.skip(startFrom);

                res = createResponse(Response.Status.PARTIAL_CONTENT, mime,
                        fis);
                res.addHeader("Content-Length", "" + dataLen);
                res.addHeader("Content-Range", "bytes " + startFrom + "-"
                        + endAt + "/" + fileLen);
                res.addHeader("ETag", etag);
            }
        } else {
            if (etag.equals(header.get("if-none-match")))
                res = createResponse(Response.Status.NOT_MODIFIED, mime, "");
            else {
                res = createResponse(Response.Status.OK, mime,
                        new FileInputStream(file));
                res.addHeader("Content-Length", "" + fileLen);
                res.addHeader("ETag", etag);
            }
        }
    } catch (IOException ioe) {
        res = createResponse(Response.Status.FORBIDDEN,
                NanoHTTPD.MIME_PLAINTEXT, "FORBIDDEN: Reading file failed.");
    }

    return res;
}
于 2013-10-26T00:27:47.227 回答
0

这是提供任何类型文件的代码

if (uri.equals("/apk")) {
        File root = Environment.getExternalStorageDirectory();
        FileInputStream fis = null;
        File file = new File(root.getAbsolutePath() + "/www/openrap/sunbird.apk");
        String mime = NanoHTTPD.getMimeTypeForFile("sunbird.apk");
        Log.d("Path", root.getAbsolutePath());
        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, mime, fis, file.length());
    }

在 Manfiest 文件中添加此权限

 <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
于 2018-12-07T07:09:18.237 回答
-1

难道你还需要添加权限 android.permission.READ_EXTERNAL_STORAGE

因为你正在读一个文件。

于 2013-10-14T11:38:37.190 回答