在Python Flask中使用send_file发送视频时,移动设备发生错误

问题描述:

我正在使用Python Flask.我想通过权限检查将媒体文件(mp4,mp3,mov等)发送给用户.我将检查数据库的用户许可权,并且我只想为经过身份验证的用户发送文件.

I am using Python Flask. I want to send media file(mp4, mp3, mov etc) to user with permission check. I will check user permission with DB and I want to send file only for authenticated user.

因此,我开始开发该系统.我使用登录名检查权限,使用Send_file将文件发送给用户.在台式机上,它运行良好.但是在我的iPad,iPhone,Android手机上,它不起作用.他们的播放器提醒无法播放此视频".在iPhone中,播放器的播放按钮不可用.

So I start to developing that system. I check permission using login, I send file to user using Send_file. On Desktop, It working well. But On my iPad, iPhone, Android phone, it didn't work. Their player alert 'cannot play this video'. In iPhone, player's play button is unavailable.

iPhone错误屏幕截图此处http://webhost.swisscom.co.kr/temp/*_iphone1.jpg

iPhone error screen shot here http://webhost.swisscom.co.kr/temp/*_iphone1.jpg

烧瓶服务器(Gunicorn)返回

Flask server(Gunicorn) return

错误:[Errno 107]传输端点未连接". 当python flask调试服务器时-错误:[错误32]管道损坏.

"error: [Errno 107] Transport endpoint is not connected". When python flask debugging server - "error: [Error 32] Broken pipe.

我在超过5台不同的服务器上进行了测试,但仍然无法正常工作.

I tested in over 5 different servers, but it still don't working.

我还使用了x-sendfile或send_from_directory,即手动构建响应标头.

I also used x-sendfile or send_from_directory, manual build response headers.

@app.route('/download/<path:filename>')
def download(filename):
    return send_file('data/file/' + filename)

在iOS7,iOS6,Android中请求视频时,Gunicorn Flask Server错误

Gunicorn Flask Server error when request video in iOS7, iOS6, android

2013-10-17 16:38:46 [14344] [ERROR] Error processing request.
Traceback (most recent call last):
  File "/usr/local/lib/python2.7/dist-packages/gunicorn/workers/sync.py", line 88, in handle
    self.handle_request(listener, req, client, addr)
  File "/usr/local/lib/python2.7/dist-packages/gunicorn/workers/sync.py", line 145, in handle_request
    client.shutdown(socket.SHUT_RDWR)
  File "/usr/lib/python2.7/socket.py", line 224, in meth
    return getattr(self._sock,name)(*args)
error: [Errno 107] Transport endpoint is not connected
2013-10-17 16:38:47 [14331] [ERROR] Error processing request.
Traceback (most recent call last):
  File "/usr/local/lib/python2.7/dist-packages/gunicorn/workers/sync.py", line 88, in handle
    self.handle_request(listener, req, client, addr)
  File "/usr/local/lib/python2.7/dist-packages/gunicorn/workers/sync.py", line 145, in handle_request
    client.shutdown(socket.SHUT_RDWR)
  File "/usr/lib/python2.7/socket.py", line 224, in meth
    return getattr(self._sock,name)(*args)
error: [Errno 107] Transport endpoint is not connected

在iOS7或iOS6或android中请求视频时,Python调试器服务器错误

Python debugger server error when request video in iOS7 or iOS6 or android

123.123.123.123 - - [17/Oct/2013 16:34:36] "GET /download/welcome.mp4 HTTP/1.1" 200 -
----------------------------------------
Exception happened during processing of request from ('110.70.52.201', 38723)
Traceback (most recent call last):
  File "/usr/lib/python2.7/SocketServer.py", line 295, in _handle_request_noblock
    self.process_request(request, client_address)
  File "/usr/lib/python2.7/SocketServer.py", line 321, in process_request
    self.finish_request(request, client_address)
  File "/usr/lib/python2.7/SocketServer.py", line 334, in finish_request
    self.RequestHandlerClass(request, client_address, self)
  File "/usr/lib/python2.7/SocketServer.py", line 651, in __init__
    self.finish()
  File "/usr/lib/python2.7/SocketServer.py", line 704, in finish
    self.wfile.flush()
  File "/usr/lib/python2.7/socket.py", line 303, in flush
    self._sock.sendall(view[write_offset:write_offset+buffer_size])
error: [Errno 32] Broken pipe

我终于解决了这个问题.

I FINALLY solved this problem.

首先,我将Nginx与Gunicorn结合使用.

First, I am using Nginx with Gunicorn.

将Nginx与Gunicorn结合使用时,可以按照以下步骤在下载文件之前检查身份验证信息.

When using Nginx with Gunicorn, you can check auth info before download file using following step.

它使用Nginx内部重定向功能.它将阻止未经身份验证的文件访问.

It is using Nginx intenal redirect only function. It will block unauthenticated access to your file.

用户-> Nginx-> Gunicorn->在python代码中检查身份验证信息->响应数据

User -> Nginx -> Gunicorn -> Check Auth info in python code -> Response Data

server {
    listen 80;
    server_name yourserver.com;

    location /download_file/ {
        internal; # Receive just internal redirect
        alias    /file/path/in/your/server/;
    }

    # Just for Gunicorn Serving (option)
    location / {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
         proxy_set_header Host $http_host;
         proxy_redirect off;

         if (!-f $request_filename) {
             proxy_pass http://service;
             break;
         }
    }
}

Python代码

@app.route('/download/<path:filename>')
def download(filename):
    if not authentication():
        abort(404)

    redirect_path = '/download_file/' + filename

    response = make_response("")
    response.headers["X-Accel-Redirect"] = redirect_path
    response.headers["Content-Type"] = mimetypes.guess_type(filename)
    return response

然后您的浏览器将接收来自Nginx的文件

Then your browser will receive file from Nginx

也可以在iOS中工作,喜欢从普通的网络服务器上进行服务.

Also working in iOS likes serving from common web server.