当前位置: 首页 > news >正文

白银网站建设熊掌号网站模块规划

白银网站建设熊掌号,网站模块规划,微分销平台搭建,台州品牌网站设计(给PHP开发者加星标#xff0c;提升PHP技能)转自#xff1a;林伯格https://breeze2.github.io/blog/scheme-nginx-php-js-upload-process前言很多网站都会有上传文件的功能#xff0c;比如上传用户头像#xff0c;上传个人简历等等#xff0c;除非是网盘类的网站#xff… (给PHP开发者加星标提升PHP技能)转自林伯格https://breeze2.github.io/blog/scheme-nginx-php-js-upload-process前言很多网站都会有上传文件的功能比如上传用户头像上传个人简历等等除非是网盘类的网站一般上传文件不会作为网站的主要功能而且如今大众的网速已经是足够的快上传几百KB的文件几乎可以秒内完成。但是随着文件大小和类型越来越庞大文件上传也就越值得我们重视。大多数网站对于上传文件的处理都是简单的前端POST上传后端验证存放然后返回访问地址。毕竟文件小网速快一瞬间的事情谁会多在意呢存在问题假设我们有一个网站基于NginXPHPJS构架网站允许用户上传一些小视频、音乐或者PPT等文件在线上展示单个文件大小限制不超过30MB那么我们要怎样实现这个上传功能呢限制上传文件的大小首先NginX要能接受最大32MB的请求(除了最大文件本身30MB再预留一些给其他请求参数)我们会修改网站的虚拟主机配置# website.conf server { client_max_body_size 32M; ...}然后PHP也要修改配置接受最大30MB的文件上传和最大32MB的POST请求# php.iniupload_max_filesize 30M;post_max_size 32M;其实单凭client_max_body_sizeNginX是不能真正限制上传文件大小的因为NginX会先让客户端(一般是浏览器)开始上传请求直到上传的内容大小超过了限制NginX才会中止上传报413 Request Entity Too Large错误没超过限制则交给PHP处理。于是PHP的upload_max_filesize和post_max_size就更没用了因为PHP获取到文件信息的时候上传过程已经结束了(这时当然是上传成功NginX中止请求的话PHP不会进场)。在NginX传递请求结果前PHP什么(比如验证用户验证权限等等)都做不了。如果用户上传了一个大于32MB的时候直到上传到32MB的时候才能告诉用户文件过大了那么前面的时间用户不就白等了吗而且服务器的带宽还是一样被消耗了。我们更希望在上传开始前就能告诉用户文件过大了。很多网站开发都会把这一步交给JS处理在新型浏览器(支持HTML5)里JS的确可以获取input文件的大小在旧的IE里也可以通过ActiveX来实现。但是JS的限制处理很容易被绕过去只要知道上传地址一个form标签就能把文件传过去form idupload_form action/path/to/upload enctypemultipart/form-data methodpost input typefile nameupload_file value/path/of/big/big/file / input typesubmit valueUpload /form正常的用户当然不会这样做但是有意攻击网站的人会。限制上传文件的速度如果服务器的入口带宽是100mbps用户的上行带宽是10mbps用户上传一个30MB的文件至少需要30秒那么在30秒内服务器的带宽只能满足10个用户上传文件带宽被占满后服务器就很难再处理其他请求了。所以限制用户上传文件的速度就很有必要。目前JS做不到限制上传文件的速度PHP也做不到。上传文件的进度用户上传一个30MB的文件至少需要30秒那么30秒内应该告知用户上传的进度不能让用户无感知的等待。HTML5改进了XMLHttpRequest对象在支持HTML5的新型浏览器里JS可以获取XMLHttpRequest上传文件的进度在旧的浏览器的也可以通过Flash与JS结合(比如SWFUpload)从而获取上传文件的进度。但是新型浏览器里Flash已经被摒弃了因而要支持新旧浏览器JS就要写成两套代码。在这里PHP也是帮不上忙因为PHP拿到传文件信息的时候上传已经结束了。解决方案网站是NginXPHPJS构架的PHP和JS解决不了的问题那应该在NginX上解决它。NginX虽然是一个现成的软件但是它还是可以继续扩展和修改的。NginX本身没有提供上传文件的复杂处理功能而在NginX官方认可的第三方扩展模块里有两个模块可以帮助我们实现复杂的上传文件功能分别是nginx-upload-module和nginx-upload-progress-module。要将nginx-upload-module和nginx-upload-progress-module编译进NginX首先要下载NginX源码和nginx-upload-module、nginx-upload-progress-module这两个模块的源码然后在NginX源码目录中在configure参数中加入这两个这两个模块最后make install大概的执行命令$ cd ~$ mkdir tmp$ cd tmp$ wget http://nginx.org/download/nginx-1.11.3.tar.gz$ tar -xvzf nginx-1.11.3.tar.gz$ git clone https://github.com/vkholodkov/nginx-upload-module.git$ git clont https://github.com/masterzen/nginx-upload-progress-module.git$ cd nginx-1.11.3$ ./configure --add-module~/tmp/nginx-upload-module --add-module~/tmp/nginx-upload-progress-module ...$ make$ make install如果系统上已经安装过NginX并且所安装NginX版本支持动态模块那么可以考虑将nginx-upload-module和nginx-upload-progress-module编译成动态模块这样就不需要重新安装NginX。nginx-module-libs上有Ubuntu系统上主线NginX版本的一些动态模块可以上面下载适配你的nginx-upload-module和nginx-upload-progress-module。下面主要介绍一下两个模块的用法nginx-upload-module当上传文件的体积小于client_max_body_size时 nginx-upload-module可以帮助我们限制上传速度使用方法见下。NginX的站点配置# website.confserver { ... client_max_body_size 32m; # 限制上传速度最大2Mbps upload_limit_rate 256k; location /upload { # 限制上传文件最大30MB upload_max_file_size 30m; # 后续交给 upload.php 处理 upload_pass /upload.php; # 指定上传文件存放目录1表示按1位散列将上传文件随机存到指定目录下的0、1、2、...、8、9目录中(这些目录要手动建立) upload_store /tmp 1; # 上传文件的访问权限user:r表示用户只读 upload_store_access user:r; # 设置请求体的字段 upload_set_form_field ${upload_field_name}_name $upload_file_name; upload_set_form_field ${upload_field_name}_content_type $upload_content_type; upload_set_form_field ${upload_field_name}_path $upload_tmp_path; # 指示后端关于上传文件的md5值和文件大小 upload_aggregate_form_field ${upload_field_name}_md5 $upload_file_md5; upload_aggregate_form_field ${upload_field_name}_size $upload_file_size; upload_pass_form_field ^submit$|^description$; # 若出现如下错误码则删除上传的文件 upload_cleanup 400 404 499 500-505; }}上传文件的页面form idupload enctypemultipart/form-data action/upload methodpost input nameupload_file typefile labelfileupload / input typesubmit valueUpload File /form处理上传结果的脚本 php// upload.phpprint_r($_REQUEST);如果对PHP解析使用了优雅链接比如Laravel那么应该这样使用NginX的站点配置# website.confserver { ... client_max_body_size 32m; # 限制上传速度最大2Mbps upload_limit_rate 256k; location / { try_files $uri $uri/ /index.php?$query_string; } location ~ \.php$ { include snippets/fastcgi-php.conf; fastcgi_param HTTP_PROXY ; fastcgi_pass unix:/run/php/php-fpm.sock; } location upload_handle { rewrite ^ /index.php last; } location /upload { # 限制上传文件最大30MB upload_max_file_size 30m; # 后续交给 index.php 处理 upload_pass upload_handle; # 指定上传文件存放目录1表示按1位散列将上传文件随机存到指定目录下的0、1、2、...、8、9目录中(这些目录要手动建立) upload_store /tmp 1; # 上传文件的访问权限user:r表示用户只读 upload_store_access user:r; # 设置请求体的字段 upload_set_form_field ${upload_field_name}_name $upload_file_name; upload_set_form_field ${upload_field_name}_content_type $upload_content_type; upload_set_form_field ${upload_field_name}_path $upload_tmp_path; # 指示后端关于上传文件的md5值和文件大小 upload_aggregate_form_field ${upload_field_name}_md5 $upload_file_md5; upload_aggregate_form_field ${upload_field_name}_size $upload_file_size; upload_pass_form_field ^submit$|^description$; # 若出现如下错误码则删除上传的文件 upload_cleanup 400 404 499 500-505; }}上传文件的页面form idupload?_token{{csrf_token()}} enctypemultipart/form-data action/upload methodpost input nameupload_file typefile labelfileupload / input typesubmit valueUpload File /formLaravel路由配置?php // routes/web.phpRoute::post(/upload, Web\IndexControllerupload)-name(upload);Laravel控制器中处理上传的方法?php // Web/IndexController.phpfunction upload() { dump(request());}nginx-upload-progress-modulenginx-upload-progress-module可以帮助我们跟踪上传的进度使用方法见下。NginX的站点配置# website.confserver { ... client_max_body_size 32m; # 开辟一个空间proxied来存储跟踪上传的信息1MB upload_progress proxied 1m; location ^~ /progress { # 报告上传的信息 report_uploads proxied; } location /upload { ... # 上传完成后仍然保存上传信息5s track_uploads proxied 5s; }}上传文件的页面和每隔一秒查询一下上传进度的脚本form idupload enctypemultipart/form-data action/upload methodpost onsubmitopenProgressBar(); return true; input nameuserfile typefile labelfileupload / input typesubmit valueUpload File /formdiv div idprogress stylewidth: 400px; border: 1px solid black div idprogressbar stylewidth: 1px; background-color: black; border: 1px solid white div div div idtp(progress)divdivscript typetext/javascript var interval null; var uuid ; function openProgressBar() { for (var i 0; i 32; i) { uuid Math.floor(Math.random() * 16).toString(16); } document.getElementById(upload).action /upload?X-Progress-ID uuid; /* 每隔一秒查询一下上传进度 */ interval window.setInterval(function () { fetch(uuid); }, 1000); } function fetch(uuid) { var req new XMLHttpRequest(); req.open(GET, /progress, 1); req.setRequestHeader(X-Progress-ID, uuid); req.onreadystatechange function () { if (req.readyState 4) { if (req.status 200) { var upload eval(req.responseText); document.getElementById(tp).innerHTML upload.state; /* 更新进度条 */ if (upload.state done || upload.state uploading) { var bar document.getElementById(progressbar); var w 400 * upload.received / upload.size; bar.style.width w px; } /* 上传完成不再查询进度 */ if (upload.state done) { window.clearTimeout(interval); } if (upload.state error) { window.clearTimeout(interval); alert(something wrong); } } } } req.send(null); }script当上传文件的体积大于client_max_body_size时 nginx-upload-module未能帮我们立刻中断上传并且不能限制上传速度但是nginx-upload-progress-module可以向前端报告文件过大的错误前端可以这样子来中断上传form idupload enctypemultipart/form-data action/upload methodpost onsubmitopenProgressBar(); return false; input nameuserfile typefile labelfileupload iduserfile / input typesubmit valueUpload File /formdiv div idprogress stylewidth: 400px; border: 1px solid black div idprogressbar stylewidth: 1px; background-color: black; border: 1px solid white div div div idtp(progress)divdivscript typetext/javascript var interval null; var uuid ; var uploadxhr null; function openProgressBar() { for (var i 0; i 32; i) { uuid Math.floor(Math.random() * 16).toString(16); } var action /upload?X-Progress-ID uuid; var file document.getElementById(userfile).files[0]; uploadxhr new XMLHttpRequest(); // uploadxhr.file file; uploadxhr.open(post, action, true); uploadxhr.setRequestHeader(Content-Type,multipart/form-data); uploadxhr.send(file); /* 每隔一秒查询一下上传进度 */ interval window.setInterval(function () { fetch(uuid); }, 1000); } function fetch(uuid) { var req new XMLHttpRequest(); req.open(GET, /progress, 1); req.setRequestHeader(X-Progress-ID, uuid); req.onreadystatechange function () { if (req.readyState 4) { if (req.status 200) { var upload eval(req.responseText); document.getElementById(tp).innerHTML upload.state; /* 更新进度条 */ if (upload.state done || upload.state uploading) { var bar document.getElementById(progressbar); var w 400 * upload.received / upload.size; bar.style.width w px; } /* 上传完成不再查询进度 */ if (upload.state done) { window.clearTimeout(interval); } if (upload.state error) { window.clearTimeout(interval); uploadxhr.abort(); alert(something wrong); } } } } req.send(null); }script另外nginx-upload-module和nginx-upload-progress-module还提供了更多的指令帮忙我们实现更复杂的上传文件功能比如断点续传等有兴趣可以阅读两个模块的官方文档了解更多。另外因为nginx-upload-module未能及时拦下体积过大的文件上传所以尽管保障了用户的正常使用可是依然不能防范恶意的流量攻击。nginx-upload-progress-module能够在一开始就检测到上传文件的体积是否过大(HTTP请求头里的Content-Length存有文件的体积大小)这时候就应该中断上传(可能是NginX限制扩展模块无法中断HTTP请求)大家有兴趣的话可以研究一下NginX源码和扩展开发。思考NginX的client_max_body_size设为32m攻击者可以上传1GB的文件直到上传到32MB的时候NginX才会中断上传服务器被消耗了32MB的流量。细想一下即使NginX在一开始就拦下了体积大于32MB的文件可是攻击者依然可以直接上传30MB大小的文件服务器还是会被消耗了30MB的流量所以在一开始就拦截的意义并不大可是上传文件的体积大于client_max_body_size时nginx-upload-module的限速功能不起作用这就成问题了NginX没有直接信任请求头的Content-Length应该有他的依据不过正常用户不会虚报吧(即使报小也不报大啊)看来这个方案还需继续完善或者借助现成的云存储服务来实现文件上传功能(可参考腾讯云COS的一次实践)。最后如果一个网站允许用户全速上传文件并持续数十秒那么这个网站一定存在被流量攻击的风险有可能是大量用户同时使用造成的也有可能是恶意的DDoS攻击(好像所有网站都会有这个风险)。要是服务器带宽被占满服务器对于一些用户就像是掉线了所以上传文件的问题必须重视。另外开发者不应该局限于一种编程语言或者一个知识领域上去思考解决问题应该涉览更多的知识领域从更多角度、更多方位去解决问题。- EOF -推荐阅读  点击标题可跳转1、Nginx 一个牛X的功能流量拷贝2、PHP下kafka的实践3、Nginx 正向代理与反向代理看完本文有收获请分享给更多人推荐关注「PHP开发者」提升PHP技能点赞和在看就是最大的支持❤️
http://wiki.neutronadmin.com/news/174574/

相关文章:

  • 利用帝国cms网站建设sdcms网站建设模板
  • 医院手机网站源码软件开发培训学校排行
  • 网站建设与管理这门课程的介绍做网站的公司北京有哪些
  • sns网站是什么江苏无锡今天的最新发布消息
  • 国网公司网站武安市精品网站开发
  • 做t恤的网站做网站的色彩搭配的小知识
  • 网站开发的项目总结网站色调代号
  • 金华 网站建设哪些网站适合用自适应
  • 国际最好的摄影作品网站竞价推广套户渠道商
  • 株洲网站搜索优化富阳网站定制开发哪家公司好
  • 手机访问不了自己做的网站吗电子商务网站平台建设
  • 网站建设中服务器的搭建方式郑州市科协网站
  • 网站备案前置审批文件网站 带数据
  • 公司网站开发策划书广告制作公司哪家好
  • 山东品牌建设网站网站底部优化文字
  • 专门做win7的网站模板免费下载网站
  • 扫描网站特征dede淮南招聘网站建设
  • 文章管理系统网站模板徐州网站无障碍建设
  • 怎么刷网站点击量上线了小程序
  • 深圳专业营销网站制作百度搜索引擎推广收费标准
  • 在discuz做网站搭建企业交流平台
  • 搭建网站要多久个人网站注册平台要多少钱
  • 做网站ps的图片公众平台是什么
  • 深圳专业做网站专业公司软件开发工具包sdk
  • 蓝韵官方网站企业网站建设功能模块
  • 有哪些做企业点评的网站石家庄网站建设外包公司
  • 1688网站建设方案书模板免费海外网站建设
  • 内江市网站建设建网通
  • 深圳做模板网站的公司网站网页直播怎么做
  • 专门做恐怖电影网站关于志愿者网站开发的论文