将二进制数据输入Django的问题

时间:2009-11-24 23:03:26

标签: python django http

我正在尝试用Django构建一个RESTful api来共享mp3 - 就在前面:它是一个玩具应用程序,从不投入生产,所以它不需要扩展或担心(我希望)有关版权恶魔。 我现在的问题是我有一个Django视图,我想成为HTTP PUT请求的端点。 PUT的标题将包含元数据,而正文将仅包含二进制文件。

这是我(尝试)击中的实际视图。请注意,日志记录表明控制流永远不会进入put()方法,我认为这是正确的,如果不是特别健壮:

class UserSong(RESTView):
    logging.debug('entering UserSong.put')
    def put(self, request, username=''):

        if request.META['Content-Type'] != 'octet/stream':
            raise Http400() 

        title = request.META['X-BD-TITLE'] if 'X-BD-TITLE' in request.META else 'title unknown'
        artist = request.META['X-BD-ARTIST'] if 'X-BD-ARTIST' in request.META else 'artist unknown' 
        album = request.META['X-BD-ALBUM'] if 'X-BD-ALBUM' in request.META else 'album unknown' 
        song_data = b6decode(request.raw_post_data)

        song = Song(title=title, artist=artist, playcount=playcount, is_sample=is_sample, song_data=song_data, album=album)
        song.save()

        return HttpResponse('OK', 'text/plain' , 201)

def __call__(self, request, *args, **kwargs):
    logging.basicConfig(filename=LOGFILE,level=logging.DEBUG)
    try:  
        if request.method == 'DELETE':
            return self.delete(request, *args, **kwargs)  
        elif request.method == 'GET':
            return self.get(request, *args, **kwargs)
        elif request.method == 'POST':
            return self.post(request, *args, **kwargs)
        elif request.method == 'PUT':
            return self.put(request, *args, **kwargs)
    except:
        raise Http404()

在测试中,我能够使用Django的单元测试框架进行单元测试,但我不相信它是准确地模仿真实生活。所以,我破解了打开httplib,并构建了一个自己的PUT。这是我以交互方式执行的代码:

>>>method = 'PUT'
>>>url = 'accounts/test/songs/'
>>>f = open('/Users/bendean/Documents/BEARBOT.mp3')
>>>data = f.read()
>>>body = data
>>>headers = {'X-BD-ARTIST' : 'BEARBOT' , 'X-BD-ALBUM':'','X-BD-TITLE':'LightningSPRKS'}
>>>headers['CONTENT-TYPE'] = 'octet/stream'
>>>import httplib
>>>c = httplib.HTTPConnection('localhost:8000')
>>>c.request(method, url, body, headers)

我得到的反应不是很好

Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File  "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/httplib.py", line 880, in request
  File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/httplib.py", line 914, in _send_request
  File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/httplib.py", line 719, in send
  File "<string>", line 1, in sendall
 error: [Errno 54] Connection reset by peer

虽然有时我得到

Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/httplib.py", line 880, in request
  File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/httplib.py", line 914, in _send_request
  File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/httplib.py", line 719, in send
  File "<string>", line 1, in sendall
error: [Errno 32] Broken pipe

我相信我的网址正常工作(GET处理程序做得很好,谢谢)。日志记录表明请求实际上并不是处理程序代码。

谷歌搜索引导我发出跟踪器,建议问题在于httplib在上传大文件时处理错误(这个是3.7 MB)。

所以,我并不羞于承认我不在这里 - 我怎样才能确定导致错误的原因?我是否正确格式化了我的请求(p.s.我也试过b64encoding the body,结果相同)?从更广泛的意义上说,我正在做什么(测试,而不是在生活中)是合理的?它与开发服务器上的可配置设置有什么关系吗?如果我尝试将这个问题放在Apache上,这些问题会消失吗?非常感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

看起来问题出在开发服务器处理大型请求中。在使用mod_wsgi部署到apache之后,这个问题就消失了。关于RESTful文件上传,我仍有很多未解决的问题......