Dev*_*xon 14 php file-upload nginx amazon-s3 hhvm
我有一个非常奇怪的问题,上传超过6GB的大文件.我的过程是这样的:
我的PHP(HHVM)和NGINX配置都将其配置设置为允许最多16GB的文件,我的测试文件只有8GB.
这是奇怪的部分,ajax 总是会超时.但是文件被成功上传,它被复制到tmp位置,存储在db,s3中的位置等等.但是即使所有执行完成(需要10-15分钟),AJAX也会运行一个小时超时时结束.
什么可能导致服务器不仅仅发送大文件的响应?
服务器端的错误日志也是空的.
Ana*_*oly 48
大文件上传是一种昂贵且容易出错的操作.Nginx和后端应配置正确的超时,以便在发生时处理慢速磁盘IO.从理论上讲,使用multipart/form-data encoding RFC 1867管理文件上传是很简单的.
根据developer.mozilla.org在multipart/form-data主体中,HTTP Content-Disposition通用标头是一个标头,可以在多部分主体的子部分上使用,以提供有关其应用的字段的信息.子部分由Content-Type标头中定义的边界分隔.在身体本身使用,Content-Disposition没有效果.
让我们看一下上传文件时会发生什么:
1)客户端将带有文件内容的HTTP请求发送到Web服务器
2)webserver接受请求并启动数据传输(如果文件大小超过限制,则返回错误413)
3)webserver开始填充缓冲区(取决于文件和缓冲区大小)
4)webserver通过文件/网络套接字将文件内容发送到后端
5)后端验证初始请求
6)后端读取文件并剪切标题(Content-Disposition,Content-Type)
7)后端转储结果文件到磁盘上
8)任何后续程序,如数据库更改
在大文件上传期间会出现几个问题:
让我们从Nginx配置新位置http:// backend/upload开始接收大文件上传,后端交互最小化(Content-Legth:0),文件只存储到磁盘.使用缓冲区Nginx将文件转储到磁盘(存储在临时目录中的文件,随机名称,无法更改),然后POST请求后端到位置http:// backend/file,文件名在X-File-中名称标题.
要保留额外信息,您可以使用带有初始POST请求的标头.例如,从初始请求获取X-Original-File-Name标头可帮助您匹配文件并将必要的映射信息存储到数据库.
让我们看看它是如何实现的:
1)配置Nginx将HTTP正文内容转储到文件中,并将其保存在client_body_in_file_only中;
2)创建新的后端端点http:// backend/file来处理临时文件名和头之间的映射X-File-Name
4)仪器AJAX查询用标题X-File-Name Nginx将用于发送帖子上传请求
组态:
location /upload {
client_body_temp_path /tmp/;
client_body_in_file_only on;
client_body_buffer_size 1M;
client_max_body_size 7G;
proxy_pass_request_headers on;
proxy_set_header X-File-Name $request_body_file;
proxy_set_body off;
proxy_redirect off;
proxy_pass http://backend/file;
}
Run Code Online (Sandbox Code Playgroud)
Nginx配置选项client_body_in_file_only与多部分数据上载不兼容,但您可以将其与AJAX即XMLHttpRequest2(二进制数据)一起使用.
如果您需要进行后端身份验证,则只能使用auth_request,例如:
location = /upload {
auth_request /upload/authenticate;
...
}
location = /upload/authenticate {
internal;
proxy_set_body off;
proxy_pass http://backend;
}
Run Code Online (Sandbox Code Playgroud)
无论初始POST内容长度大小如何,预上载身份验证逻辑都可以防止未经身份验证的请求.