问题描述
||
我目前正在尝试使用Python提供MP3文件。问题是我只能播放一次MP3。之后,媒体控件停止响应,因此我需要重新加载整个页面才能再次收听MP3。 (在Chrome中测试)
问题:运行以下脚本,并在浏览器中输入http://127.0.0.1/test.mp3,将会返回MP3文件,只有刷新页面后才能播放该文件
笔记:
将页面另存为HTML并直接通过Chrome加载(没有Python服务器)会使问题消失。
用Apache提供文件可以解决该问题,但是这过于矫kill过正:我想使脚本非常易于使用,并且不需要安装Apache。
这是我使用的代码:
import string
import os
import urllib
import socket
# Setup web server import string,cgi,time
import string,time
from os import curdir,sep
from BaseHTTPServer import BaseHTTPRequestHandler,HTTPServer
import hashlib
class MyHandler(BaseHTTPRequestHandler):
def do_GET(self):
try:
# serve mp3 files
if self.path.endswith(\".mp3\"):
print curdir + sep + self.path
f = open(curdir + sep + self.path,\'rb\')
st = os.fstat( f.fileno() )
length = st.st_size
data = f.read()
md5 = hashlib.md5()
md5.update(data)
md5_key = self.headers.getheader(\'if-none-match\')
if md5_key:
if md5_key[1:-1] == md5.hexdigest():
self.send_response(304)
self.send_header(\'ETag\',\'\"{0}\"\'.format(md5.hexdigest()))
self.send_header(\'Keep-Alive\',\'timeout=5,max=100\')
self.end_headers()
return
self.send_response(200)
self.send_header(\'Content-type\',\'audio/mpeg\')
self.send_header(\'Content-Length\',length )
self.send_header(\'ETag\',\'\"{0}\"\'.format(md5.hexdigest()))
self.send_header(\'Accept-Ranges\',\'bytes\')
self.send_header(\'Last-Modified\',time.strftime(\"%a %d %b %Y %H:%M:%s GMT\",time.localtime(os.path.getmtime(\'test.mp3\'))))
self.end_headers()
self.wfile.write(data)
f.close()
return
except IOError:
self.send_error(404,\'File Not Found: %s\' % self.path)
from SocketServer import ThreadingMixIn
class ThreadedHTTPServer(ThreadingMixIn,HTTPServer):
pass
if __name__ == \"__main__\":
try:
server = ThreadedHTTPServer((\'\',80),MyHandler)
print \'started httpserver...\'
server.serve_forever()
except KeyboardInterrupt:
print \'^C received,shutting down server\'
server.socket.close()
解决方法
BaseServer
是单线程的,应使用ForkingMixIn
或ThreadingMixIn
支持多个连接。
例如替换行:
server = HTTPServer((\'\',80),MyHandler)
与
from SocketServer import ThreadingMixIn
class ThreadedHTTPServer(ThreadingMixIn,HTTPServer):
pass
server = ThreadedHTTPServer((\'\',MyHandler)
,编辑:在意识到Mapadd仅计划在实验室中使用它之前,我写了很多这样的内容。他的用例可能不需要WSGI。
如果您愿意将其作为wsgi应用程序运行(出于任何实际可扩展性的考虑,我建议通过vanilla CGI进行运行),则可以使用下面包含的脚本。
我自由地修改了您的源代码……这与上面的假设一致。.顺便说一句,您应该花一些时间检查您的html是否合理合规...这将有助于确保您获得更好的跨浏览器兼容性。 。原始文件没有<head>
或<body>
标签...我的(下面)严格是html原型,可以进行改进。
要运行此程序,您只需在shell中运行python可执行文件,然后在8080上浏览到该计算机的ipaddress。如果您是在生产网站上进行此操作,则应该使用lighttpd或apache来提供文件,但是因为这很简单对于实验室使用,嵌入式wsgi参考服务器应该可以。如果要在apache或lighttpd中运行,请替换文件底部的“ 8”行。
另存为mp3.py
from webob import Request
import re
import os
import sys
####
#### Run with:
#### twistd -n web --port 8080 --wsgi mp3.mp3_app
_MP3DIV = \"\"\"<div id=\"musicHere\"></div>\"\"\"
_MP3EMBED = \"\"\"<embed src=\"mp3/\" loop=\"true\" autoplay=\"false\" width=\"145\" height=\"60\"></embed>\"\"\"
_HTML = \'\'\'<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\"><html><head></head><body> Hello %s %s</body></html> \'\'\' % (_MP3DIV,_MP3EMBED)
def mp3_html(environ,start_response):
\"\"\"This function will be mounted on \"/\" and refer the browser to the mp3 serving URL.\"\"\"
start_response(\'200 OK\',[(\'Content-Type\',\'text/html\')])
return [_HTML]
def mp3_serve(environ,start_response):
\"\"\"Serve the MP3,one chunk at a time with a generator\"\"\"
file_path = \"/file/path/to/test.mp3\"
mimetype = \"application/x-mplayer2\"
size = os.path.getsize(file_path)
headers = [
(\"Content-type\",mimetype),(\"Content-length\",str(size)),]
start_response(\"200 OK\",headers)
return send_file(file_path,size)
def send_file(file_path,size):
BLOCK_SIZE = 4096
fh = open(file_path,\'r\')
while True:
block = fh.read(BLOCK_SIZE)
if not block:
fh.close()
break
yield block
def _not_found(environ,start_response):
\"\"\"Called if no URL matches.\"\"\"
start_response(\'404 NOT FOUND\',\'text/plain\')])
return [\'Not Found\']
def mp3_app(environ,start_response):
\"\"\"
The main WSGI application. Dispatch the current request to
the functions andd store the regular expression
captures in the WSGI environment as `mp3app.url_args` so that
the functions from above can access the url placeholders.
If nothing matches call the `not_found` function.
\"\"\"
# map urls to functions
urls = [
(r\'^$\',mp3_html),(r\'mp3/?$\',mp3_serve),]
path = environ.get(\'PATH_INFO\',\'\').lstrip(\'/\')
for regex,callback in urls:
match = re.search(regex,path)
if match is not None:
# assign http environment variables...
environ[\'mp3app.url_args\'] = match.groups()
return callback(environ,start_response)
return _not_found(environ,start_response)
从bash shell运行,输入::10ѭ(保存mp3.py的目录)(或仅将mp3.py放在ѭ11的某个位置)。
现在浏览到外部ip(即http://some.ip.local:8080 /),它将直接为mp3提供服务。
我尝试运行原始应用程序,因为它被发布了,但无法获取它作为mp3的源代码,它在Linux中出现错误,对我咆哮...