【问题标题】:Serve mp3 stream for android with Laravel使用 Laravel 为 android 提供 mp3 流
【发布时间】:2016-09-29 14:34:57
【问题描述】:

这是我的问题:我正在编写一个 laravel 后端,它必须提供一个 mp3 文件,该文件必须使用 android 标准媒体播放器进行复制。

对于 laravel 后端,我需要使用 JWT 来处理身份验证,因此对于每个请求标头,我必须将“授权”字段设置为“Bearer {token}”。
laravel 路由是“/songs/{id}”,并以这种方式处理:

public function getSong(Song $song) {
    $file = new File(storage_path()."/songs/".$song->path.".mp3");

    $headers = array();
    $headers['Content-Type'] = 'audio/mpeg, audio/x-mpeg, audio/x-mpeg-3, audio/mpeg3';
    $headers['Content-Length'] = $file->getSize();
    $headers['Content-Transfer-Encoding'] = 'binary';
    $headers['Accept-Range'] = 'bytes';
    $headers['Cache-Control'] = 'must-revalidate, post-check=0, pre-check=0';
    $headers['Connection'] = 'Keep-Alive';
    $headers['Content-Disposition'] = 'attachment; filename="'.$song->path.'.mp3"';

    $user = \Auth::user();
    if($user->activated_at) {
        return Response::download($file, $song->path, $headers);
    }
    \App::abort(400);
}

在 android 端,我使用 MediaPlayer 以这种方式流式传输 mp3 文件:

media_player = new MediaPlayer();
    try {
        media_player.setAudioStreamType(AudioManager.STREAM_MUSIC);

        String token = getSharedPreferences("p_shared", MODE_PRIVATE).getString("token", null);
        Map<String, String> headers = new HashMap<>();
        headers.put("Authorization", "Bearer " + token);

        media_player.setDataSource(
            getApplicationContext(),
            Uri.parse(ConnectionHelper.SERVER + "/songs/" + song.getId()),
            headers
        );
    } catch (IOException e) {
        finish();
        Toast.makeText(
                Round.this,
                "Some error occurred. Retry in some minutes.",
                Toast.LENGTH_SHORT
        ).show();
    }
    media_player.setOnCompletionListener(this);
    media_player.setOnErrorListener(this);
    media_player.setOnPreparedListener(this);

但是每次我执行代码时,我都会在错误侦听器上得到额外的代码 -1005,这意味着 ERROR_CONNECTION_LOST

【问题讨论】:

    标签: android laravel streaming mp3 android-mediaplayer


    【解决方案1】:

    问题Response::download(...) 不产生流,所以我无法提供我的 .mp3 文件。

    解决方案: 正如 Symfony HttpFoundation doc. 在服务文件段落中所说:

    "if you are serving a static file, you can use a BinaryFileResponse"
    

    我需要提供的 .mp3 文件是服务器中的静态文件并存储在“/storage/songs/”中,因此我决定使用 BinaryFileResponse,而提供 .mp3 的方法变为:

    use Symfony\Component\HttpFoundation\BinaryFileResponse;
    
    [...]
    
    public function getSong(Song $song) {
        $path = storage_path().DIRECTORY_SEPARATOR."songs".DIRECTORY_SEPARATOR.$song->path.".mp3");
    
        $user = \Auth::user();
        if($user->activated_at) {
            $response = new BinaryFileResponse($path);
            BinaryFileResponse::trustXSendfileTypeHeader();
    
            return $response;
        }
        \App::abort(400);
    }
    

    BinaryFileResponse 自动处理请求并允许您完全提供文件(通过仅使用 Http 200 代码发出一个请求)或拆分以实现较慢的连接(使用 Http 206 代码的更多请求和一个使用 200 代码的最终请求)。
    如果您有 mod_xsendfile,您可以通过添加以下内容来使用(以加快流式传输):

    BinaryFileResponse::trustXSendfileTypeHeader();
    

    Android 代码无需更改即可流式传输文件。

    【讨论】:

    • 真的非常感谢,我搜索了很多。救生员
    • 当我使用“$response =new BinaryFileResponse($path);”时我收到此错误:Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException:文件“127.0.0.1:8000/data/media/music-files/1.mp3”在文件/var/www/html/Mifa/vendor/symfony/http-foundation/File/File 中不存在。 php 在第 36 行,但该文件存在。
    • 您不必使用您在浏览器中放置的文件地址,您必须从服务器构建路径,因此您应该执行以下操作: $path = public_path('data/媒体/音乐文件/1.mp3');并尝试这种方式。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-02-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-26
    • 2017-11-02
    • 1970-01-01
    相关资源
    最近更新 更多