使用Laravel为android服务mp3流 [英] Serve mp3 stream for android with Laravel

查看:84
本文介绍了使用Laravel为android服务mp3流的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我的问题:我正在编写laravel后端,该后端必须提供mp3文件,该文件必须通过使用android标准媒体播放器来复制.

对于laravel后端,我需要使用JWT处理身份验证,因此在每个请求标头上,我都必须将"Authorization"字段设置为" Bearer {token} ".
laravel路由为"/songs/{id} ",并通过以下方式进行处理:

Here's my problem: I'm writing a laravel backend which have to serve an mp3 file that had to be reproduced by using the android standard media player.

For the laravel backend I need to use JWT to handle authentication so on every request headers I have to set the "Authorization" field to "Bearer {token}" .
The laravel route is "/songs/{id}" and is handled in this way:

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文件:

On the android side I'm using the MediaPlayer to stream the mp3 file in this way:

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 .

But every time I execute the code I get extra code -1005 on the error listener that means ERROR_CONNECTION_LOST.

推荐答案

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

The problem: Response::download(...) doesn't produce a stream, so I can't serve my .mp3 file.

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

The solution: As Symfony HttpFoundation doc. says in the serving file paragraph:

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

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

The .mp3 files I need to serve are statics in the server and stored in "/storage/songs/" so I decided to use the BinaryFileResponse, and the method for serving .mp3 became:

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 ,则可以通过添加以下内容来使用(使流式传输更快):

The BinaryFileResponse automatically handle the requests and allow you to serve the file entirely (by making just one request with Http 200 code) or splitted for slower connection (more requests with Http 206 code and one final request with 200 code).
If you have the mod_xsendfile you can use (to make streaming faster) by adding:

BinaryFileResponse::trustXSendfileTypeHeader();

无需更改android代码即可流式传输文件.

The android code doesn't need to change in order to stream the file.

这篇关于使用Laravel为android服务mp3流的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆