问题
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.
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 error screen shot here http://webhost.swisscom.co.kr/temp/stackoverflow_iphone1.jpg
Flask server(Gunicorn) return
"error: [Errno 107] Transport endpoint is not connected". When python flask debugging server - "error: [Error 32] Broken pipe.
I tested in over 5 different servers, but it still don't working.
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)
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
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
回答1:
To support streaming media on iOS devices, the web server needs to support sending 206 responses (partial content) based on an incoming range header. There are a few examples of send_file replacements that handle this for you, like this one on the mailing list, or this one (NB: I havent tried these exact examples myself, but have implemented something similar for exactly this - so iOS will play videos correctly)
回答2:
I FINALLY solved this problem.
First, I am using Nginx with Gunicorn.
When using Nginx with Gunicorn, you can check auth info before download file using following step.
It is using Nginx intenal redirect only function. It will block unauthenticated access to your file.
User -> Nginx -> Gunicorn -> Check Auth info in python code -> Response Data
Nginx Config
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 Code
@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
Then your browser will receive file from Nginx
Also working in iOS likes serving from common web server.
Information from
http://mattspitz.me/2013/11/20/serving-authenticated-media-with-nginx.html
来源:https://stackoverflow.com/questions/19421014/error-occurred-in-mobile-when-send-video-using-send-file-in-python-flask