我尝试构建一个使用XML HTTP请求向用户发送视频的Web应用程序。
当视频较小(约100KB)时,它可以正常工作,但当它们较大(约5MB)时,HTTP会话通常会在传输完成之前关闭。
Chromium显示以下错误消息:
GET http://mysite.rhcloud.com/myvideo.mp4 net::ERR_CONTENT_LENGTH_MISMATCH
服务器(Openshift免费服务)显示以下错误:
[error] [client XX.XX.XX.XX] mod_wsgi (pid=XXX): Exception occurred processing WSGI script '/var/lib/openshift/XXX/app-root/runtime/repo/wsgi.py'.
[error] [client XX.XX.XX.XX] IOError: failed to write data
问题只在服务器是远程的时候重现,当我在本地运行服务器时(使用wsgiref.simple_server)它运行良好。
在Wireshark中我可以看到浏览器(Linux Mint 32位上的Chromium)在视频下载完成之前将TCP FIN发送到服务器。
服务器是一个WSGI应用程序,用Python编写并发送如下视频:
ctype = 'video/mp4'
fixed_path = fix_path(environ['PATH_INFO'][1:])
file_size = os.stat(fixed_path).st_size
response_headers = [('Content-Type', ctype), ('Content-Length', str(file_size))]
start_response(status, response_headers)
return send_file_in_chunks(fixed_path)
其中send_file_in_chunks是一个生成器:
def send_file_in_chunks(path):
with open(path, 'rb') as file_to_send:
while True:
chunk = file_to_send.read(10000)
if chunk == '':
break
yield chunk
这是客户端代码:
var req = new XMLHttpRequest();
req.open('GET', path, true);
req.responseType = 'blob';
req.addEventListener('load', myHandler);
req.onerror = function() {}
req.send();
修改
我发现了一种解决方法,导致问题发生频率降低 - 在发送每个新请求之前,请休息几秒钟(使用setTimeout)。所以这个问题可能与并发的AJAX请求限制有关。