如何使用内置 python http 服务器提供 mp3 文件
我目前正在尝试使用 Python 提供 MP3 文件。问题是我只能播放 MP3 一次。之后媒体控件停止响应,我需要重新加载整个页面才能再次收听 MP3。 (在 Chrome 中测试)
问题:运行下面的脚本,并输入 http://127.0。 0.1/test.mp3 在我的浏览器上将返回一个 MP3 文件,只有刷新页面才能重播。
注意:
将页面保存为 HTML 并直接使用 Chrome 加载(无需 Python 服务器)将使得这问题消失。
使用 Apache 提供文件可以解决问题,但这有点过分了:我想让脚本非常易于使用,并且不需要安装 Apache。
这是我使用的代码:
import string
import os
import urllib
import socket
# Setup web server import string,cgi,time
import string,cgi,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()
I am currently trying to serve MP3 Files using Python. The problem is that I can only play the MP3 once. Afterwards media controls stop responding and I need to reload entirely the page to be able to listen again to the MP3. (tested in Chrome)
Problem: running the script below, and entering http://127.0.0.1/test.mp3 on my browser will return an MP3 files which can be replayed only if I refresh the page
Notes:
Saving the page as HTML and loading it directly with Chrome (without Python server) would make the problem disappear.
Serving the file with Apache would solve the problem, but this is overkilled: I want to make the script very easy to use and not require installing Apache.
Here is the code I use:
import string
import os
import urllib
import socket
# Setup web server import string,cgi,time
import string,cgi,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()
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
BaseServer
是单线程的,您应该使用ForkingMixIn
或ThreadingMixIn
来支持多个连接。例如,将行:替换
为
BaseServer
is single-threaded, you should use eitherForkingMixIn
orThreadingMixIn
to support multiple connections.For example replace line:
with
编辑:在我意识到 Mapadd 只计划在实验室中使用它之前,我写了很多内容。他的用例可能不需要 WSGI。
如果您愿意将其作为 wsgi 应用程序 运行(我会推荐使用普通 CGI 来实现真正的可扩展性) ),您可以使用我在下面包含的脚本。
我冒昧修改了你的源代码...这符合上面的假设..顺便说一句,你应该花一些时间检查你的 html 是否合理合规...这将有助于确保你获得更好的跨浏览器兼容性..原始版本没有
或
标签...我的(下面)是严格的原型 html,可以改进。
要运行它,您只需在 shell 中运行 python 可执行文件并浏览到 8080 上机器的 IP 地址。如果您是为生产网站执行此操作,我们应该使用 lighttpd 或 apache 来提供文件,但因为这只是对于实验室使用,嵌入式 wsgi 参考服务器应该没问题。如果您想在 apache 或 lighttpd 中运行,请替换文件底部的
WSGIServer
行。另存为 mp3.py
从 bash shell 运行: twistd -n web --port 8080 --wsgi mp3.mp3_app 从保存 mp3.py 的目录(或者只是将 mp3.py 放在某处)在 $PYTHONPATH 中)。
现在浏览外部IP(即http://some.ip.local:8080/)并它将直接提供 mp3 服务。
我尝试运行你发布的原始应用程序,但无法让它获取 mp3,它在 linux 中向我发出错误......
EDIT: I wrote much of this before I realized Mapadd only planned to use this in a lab. WSGI probably is not required for his use case.
If you are willing to run this as a wsgi app (which I would recommend over vanilla CGI for any real scalability), you can use the script I have included below.
I took the liberty of modifying your source... this works with the assumptions above.. btw, you should spend some time checking that your html is reasonably compliant... this will help ensure that you get better cross-browser compatibility... the original didn't have
<head>
or<body>
tags... mine (below) is strictly prototype html, and could be improved.To run this, you just run the python executable in your shell and surf to the ipaddress of the machine on 8080. If you were doing this for a production website, we should be using lighttpd or apache for serving files, but since this is simply for lab use, the embedded wsgi reference server should be fine. Substitute the
WSGIServer
line at the bottom of the file if you want to run in apache or lighttpd.Save as mp3.py
Run from the bash shell with:
twistd -n web --port 8080 --wsgi mp3.mp3_app
from the directory where you saved mp3.py (or just put mp3.py somewhere in$PYTHONPATH
).Now surf to the external ip (i.e. http://some.ip.local:8080/) and it will serve the mp3 directly.
I tried running your original app as it was posted, and could not get it to source the mp3, it barked at me with an error in linux...