Python Requests返回文件样对象以进行流式传输

15

我创建了一个类似这样的请求对象:

 obj.mp3 = requests.get('http://foo.com/bar.mp3', stream=True)

我曾以为只需要将obj.mp3对象输入任何期望文件或URI的音频播放器中,但很明显这种想法是错误的:没有任何声音出现。以下是完整代码:

#views.py

class ArticleDetailView(DetailView):
    model = Article
    template_name = 'song.html'

    def get_object(self):
        obj = super(ArticleDetailView, self).get_object()

        #code to store mp3 url in obj.mp3 and other stuff

        if obj.mp3:
            obj.mp3 = requests.get(obj.mp3, stream=True).content
        return obj

#song.html
<div class="audio">
  <audio src={{ article.mp3 }} type="audio/mpeg"> 
</div>
什么是处理来自requests的返回结果,以便我可以使用播放器流式传输的正确方式?我知道至少我可以将 obj.mp3 写入文件,然后只需将播放器指向文件位置,但我正在尝试避免将文件写入磁盘。
谢谢。
3个回答

29

有一个属性Response.raw,它已经是类似文件的对象了。

resp = requests.get(url, stream=True)
resp.raw # is what you need

使用io.BytesIO(resp.content)不是首选,因为在幕后你会两次读取相同数量的数据(也会占用内存):访问resp.content会从网络流中读取所有内容,然后io.BytesIO(resp.content)再次分配相同数量的内存,最后再从BytesIO对象中读取。


2
请注意,Response.raw 不会像此处所述一样尊重传输编码。因此,使用raw可能会根据 Web 服务器而有所不同。 - JojOatXGME
阅读完问题#465后,我不确定我上一条评论中提到的问题是否仍然存在。 - JojOatXGME
4
看起来你可以添加 resp.raw.decode_content = True 来解决这个问题。 - JojOatXGME

10

查看io模块,以使用类似文件的对象。

可能您可以使用io.BytesIO,您可以使用Response.content初始化它。这样,而不是字节列表,您将获得一个类似文件的对象。

import io
resp = requests.get(url, stream=True)
obj.mp3 = io.BytesIO(resp.content)

经过数小时的尝试,我得出结论:这似乎根本不可能。Django模板需要一个字符串,特别是对于任何音频播放器,该字符串需要表示URL或指向媒体的路径。然而,你和我都返回了一个对象。无论如何,还是谢谢。 - eN_Joy

1
Django的职责是生成HTML代码,然后由浏览器解释。 浏览器需要流式传输音频。 您需要通过Django模板传递mp3网址,以便像http://www.jwplayer.com/这样的播放器可以在客户端上进行流式传输。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接