久久久久久久av_日韩在线中文_看一级毛片视频_日本精品二区_成人深夜福利视频_武道仙尊动漫在线观看

通過 PHP 或 Apache 從服務(wù)器端上傳 HTTP 文件

Break HTTP file uploading from server side by PHP or Apache(通過 PHP 或 Apache 從服務(wù)器端上傳 HTTP 文件)
本文介紹了通過 PHP 或 Apache 從服務(wù)器端上傳 HTTP 文件的處理方法,對(duì)大家解決問題具有一定的參考價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧!

問題描述

當(dāng)上傳大文件(>100M)到服務(wù)器時(shí),PHP 總是首先接受來自瀏覽器的整個(gè)數(shù)據(jù) POST.我們無法注入上傳過程.

When uploading big file (>100M) to server, PHP always accept entire data POST from browser first. We cannot inject into the process of uploading.

例如,在我的 PHP 代碼中,在將整個(gè)數(shù)據(jù)發(fā)送到服務(wù)器之前檢查token"的值是IMPOSSIBLE:

For example, check the value of "token" before entire data send to server is IMPOSSIBLE in my PHP code:

<form enctype="multipart/form-data" action="upload.php?token=XXXXXX" method="POST">
    <input type="hidden" name="MAX_FILE_SIZE" value="3000000" />
    Send this file: <input name="userfile" type="file" />
    <input type="submit" value="Send File" />
</form>

所以我嘗試像這樣使用 mod_rewrite:

So I've try to use mod_rewrite like this:

RewriteEngine On
RewriteMap mymap prg:/tmp/map.php
RewriteCond %{QUERY_STRING} ^token=(.*)$ [NC]
RewriteRule ^/upload/fake.php$ ${mymap:%1} [L]

map.php

#!/usr/bin/php
<?php
define("REAL_TARGET", "/upload/real.php
");
define("FORBIDDEN", "/upload/forbidden.html
");

$handle = fopen ("php://stdin","r");
while($token = trim(fgets($handle))) {
file_put_contents("/tmp/map.log", $token."
", FILE_APPEND);
    if (check_token($token)) {
        echo REAL_TARGET;
    } else {
        echo FORBIDDEN;
    }
}

function check_token ($token) {//do your own security check
    return substr($token,0,4) === 'alix';
}

但是......它再次失敗.mod_rewrite 在這種情況下看起來工作太晚了.數(shù)據(jù)仍然完全傳輸.

But ... It fails again. mod_rewrite looks working too late in this situation. Data still transfer entirely.

然后我嘗試了 Node.js,就像這樣(代碼片段):

Then I tried Node.js, like this (code snip):

var stream = new multipart.Stream(req);
stream.addListener('part', function(part) {
    sys.print(req.uri.params.token+"
");
    if (req.uri.params.token != "xxxx") {//check token
      res.sendHeader(200, {'Content-Type': 'text/plain'});
      res.sendBody('Incorrect token!');
      res.finish();
      sys.puts("
=> Block");
      return false;
    }

結(jié)果是...失敗再次.

所以請(qǐng)幫我找到解決這個(gè)問題的正確路徑或者告訴我沒有辦法.

So please help me to find the correct path to resolve this issue or tell me there is no way.

相關(guān)問題:

PHP (使用 Apache 或 Nginx)在 POST 請(qǐng)求完成之前檢查 HTTP 標(biāo)頭?

有人能告訴我如何讓這個(gè)腳本在開始上傳過程之前而不是在上傳文件之后檢查密碼嗎?

推薦答案

首先,你可以試試這段代碼自己使用我為此創(chuàng)建的 GitHub 存儲(chǔ)庫.只需克隆存儲(chǔ)庫并運(yùn)行 node header.

First of all, you can try this code yourself using the GitHub repo I created for this. Just clone the repository and run node header.

(劇透,如果您正在閱讀本文,并且在時(shí)間壓力下需要做某事而沒有心情學(xué)習(xí)(:(),最后有一個(gè)更簡(jiǎn)單的解決方案)

(Spoiler, if you're reading this and are under time pressure to get something to work and not in the mood to learn ( :( ), there is a simpler solution at the end)

這是一個(gè)很好的問題.您所要求的是很有可能并且不需要客戶端,只需更深入地了解 HTTP 協(xié)議的工作原理,同時(shí)展示 node.js 的運(yùn)行方式:)

This is a great question. What you are asking for is very possible and no clientside is needed, just a deeper understanding of how the HTTP protocol works while showing how node.js rocks :)

如果我們深入了解底層 TCP 協(xié)議 和針對(duì)這種特定情況,我們自己處理 HTTP 請(qǐng)求.Node.js 讓您可以使用內(nèi)置的 net 模塊輕松完成此操作.

This can be made easy if we go one level deeper to the underlying TCP protocol and process the HTTP requests ourselves for this specific case. Node.js lets you do this easily using the built in net module.

首先,讓我們看看 HTTP 請(qǐng)求是如何工作的.

First, let's look at how HTTP requests work.

一個(gè) HTTP 請(qǐng)求包含在由 CRLF ( ) 分隔的鍵值對(duì)的一般格式.我們知道,當(dāng)我們到達(dá)一個(gè)雙 CRLF(即 )時(shí),header 部分就結(jié)束了.

An HTTP request consists of a headers section in the general format of key:value pairs seperated by CRLF ( ). We know that the header section ended when we reach a double CRLF (that is ).

典型的 HTTP GET 請(qǐng)求可能如下所示:

A typical HTTP GET request might look something like this:

GET /resource HTTP/1.1  
Cache-Control: no-cache  
User-Agent: Mozilla/5.0 

Hello=World&stuff=other

空行"之前的頂部是標(biāo)題部分,底部是請(qǐng)求的正文.您的請(qǐng)求在 body 部分看起來會(huì)有所不同,因?yàn)樗怯?multipart/form-data 編碼的,但標(biāo)頭將保持相似讓我們探索這如何適用于我們.

The top part before the 'empty line' is the headers section and the bottom part is the body of the request. Your request will look a bit differently in the body section since it is encoded with multipart/form-data but the header will remain similarLet's explore how this applies to us.

我們可以在 TCP 中監(jiān)聽原始請(qǐng)求并讀取我們得到的數(shù)據(jù)包,直到我們讀取我們談到的雙重 crlf.然后我們將檢查我們已經(jīng)擁有的短標(biāo)題部分,以進(jìn)行我們需要的任何驗(yàn)證.在我們這樣做之后,如果驗(yàn)證沒有通過(例如通過簡(jiǎn)單地結(jié)束 TCP 連接),我們可以結(jié)束請(qǐng)求,或者通過它.這允許我們不接收或讀取請(qǐng)求正文,而只接收更小的標(biāo)頭.

We can listen to the raw request in TCP and read the packets we get until we read that double crlf we talked about. Then we will check the short header section which we already have for whatever validation we need. After we do that, we can either end the request if validation did not pass (For example by simply ending the TCP connection), or pass it through. This allows us to not receive or read the request body, but just the headers which are much smaller.

將其嵌入到現(xiàn)有應(yīng)用程序中的一種簡(jiǎn)單方法是將來自它的請(qǐng)求代理到特定用例的實(shí)際 HTTP 服務(wù)器.

One easy way to embed this into an already existing application is to proxy requests from it to the actual HTTP server for the specific use case.

這個(gè)解決方案是最簡(jiǎn)單的.這只是一個(gè)建議.

This solution is as bare bones as it gets. It is just a suggestion.

這是工作流程:

  1. 我們需要 node.js 中的 net 模塊,它允許我們?cè)?node.js 中創(chuàng)建 tcp 服務(wù)器

  1. We require the net module in node.js which allows us to create tcp servers in node.js

使用 net 模塊創(chuàng)建一個(gè) TCP 服務(wù)器,它將監(jiān)聽數(shù)據(jù):var tcpServer = net.createServer(function (socket) {... .別忘了告訴它監(jiān)聽正確的端口

Create a TCP server using the net module which will listen to data: var tcpServer = net.createServer(function (socket) {... . Don't forget to tell it to listen to the correct port

  • 在該回調(diào)中,偵聽數(shù)據(jù)事件 socket.on("data",function(data){ ,每當(dāng)數(shù)據(jù)包到達(dá)時(shí)就會(huì)觸發(fā).
  • 從 'data' 事件中讀取傳遞緩沖區(qū)的數(shù)據(jù),并將其存儲(chǔ)在一個(gè)變量中
  • 檢查雙 CRLF,這確保請(qǐng)求 HEADER 部分已經(jīng)結(jié)束 根據(jù)HTTP 協(xié)議
  • 假設(shè)驗(yàn)證是一個(gè)標(biāo)頭(用你的話來說是令牌)在解析只是標(biāo)頭后檢查它,(也就是說,我們得到了雙 CRLF).這在檢查內(nèi)容長(zhǎng)度標(biāo)頭時(shí)也有效.
  • 如果您發(fā)現(xiàn)標(biāo)頭未檢出,請(qǐng)調(diào)用 socket.end() 以關(guān)閉連接.
    • Inside that callback, listen to data events socket.on("data",function(data){ , which will trigger whenever a packet arrives.
    • read the data of the passed buffer from the 'data' event, and store that in a variable
    • check for double CRLF, this ensures that the request HEADER section has ended according to the HTTP protocol
    • Assuming that the validation is a header (token in your words) check it after parsing just the headers , (that is, we got the double CRLF). This also works when checking for the content-length header.
    • If you notice that the headers don't check out, call socket.end() which will close the connection.
    • 讀取標(biāo)題的方法:

      function readHeaders(headers) {
          var parsedHeaders = {};
          var previous = "";    
          headers.forEach(function (val) {
              // check if the next line is actually continuing a header from previous line
              if (isContinuation(val)) {
                  if (previous !== "") {
                      parsedHeaders[previous] += decodeURIComponent(val.trimLeft());
                      return;
                  } else {
                      throw new Exception("continuation, but no previous header");
                  }
              }
      
              // parse a header that looks like : "name: SP value".
              var index = val.indexOf(":");
      
              if (index === -1) {
                  throw new Exception("bad header structure: ");
              }
      
              var head = val.substr(0, index).toLowerCase();
              var value = val.substr(index + 1).trimLeft();
      
              previous = head;
              if (value !== "") {
                  parsedHeaders[head] = decodeURIComponent(value);
              } else {
                  parsedHeaders[head] = null;
              }
          });
          return parsedHeaders;
      };
      

      一種檢查數(shù)據(jù)事件緩沖區(qū)中雙 CRLF 的方法,如果它存在于對(duì)象中,則返回其位置:

      A method for checking double CRLF in a buffer you get on a data event, and return its location if it exists in an object:

      function checkForCRLF(data) {
          if (!Buffer.isBuffer(data)) {
              data = new Buffer(data,"utf-8");
          }
          for (var i = 0; i < data.length - 1; i++) {
              if (data[i] === 13) { //
                  if (data[i + 1] === 10) { //
      
                      if (i + 3 < data.length && data[i + 2] === 13 && data[i + 3] === 10) {
                          return { loc: i, after: i + 4 };
                      }
                  }
              } else if (data[i] === 10) { //
      
      
                  if (data[i + 1] === 10) { //
      
                      return { loc: i, after: i + 2 };
                  }
              }
          }    
          return { loc: -1, after: -1337 };
      };
      

      還有這個(gè)小實(shí)用方法:

      function isContinuation(str) {
          return str.charAt(0) === " " || str.charAt(0) === "	";
      }
      

      實(shí)施

      var net = require("net"); // To use the node net module for TCP server. Node has equivalent modules for secure communication if you'd like to use HTTPS
      
      //Create the server
      var server = net.createServer(function(socket){ // Create a TCP server
          var req = []; //buffers so far, to save the data in case the headers don't arrive in a single packet
          socket.on("data",function(data){
              req.push(data); // add the new buffer
              var check = checkForCRLF(data);
              if(check.loc !== -1){ // This means we got to the end of the headers!
                  var dataUpToHeaders= req.map(function(x){
                      return x.toString();//get buffer strings
                  }).join("");
                  //get data up to /r/n
                  dataUpToHeaders = dataUpToHeaders.substring(0,check.after);
                  //split by line
                  var headerList = dataUpToHeaders.trim().split("
      ");
                  headerList.shift() ;// remove the request line itself, eg GET / HTTP1.1
                  console.log("Got headers!");
                  //Read the headers
                  var headerObject = readHeaders(headerList);
                  //Get the header with your token
                  console.log(headerObject["your-header-name"]);
      
                  // Now perform all checks you need for it
                  /*
                  if(!yourHeaderValueValid){
                      socket.end();
                  }else{
                               //continue reading request body, and pass control to whatever logic you want!
                  }
                  */
      
      
              }
          });
      }).listen(8080); // listen to port 8080 for the sake of the example
      

      如果您有任何問題,請(qǐng)隨時(shí)提問:)

      If you have any questions feel free to ask :)

      但這有什么好玩的?如果您最初跳過此處,您將不會(huì)了解 HTTP 的工作原理:)

      But what's the fun in that? If you skipped here initially, you wouldn't learn how HTTP works :)

      Node.js 有一個(gè)內(nèi)置的 http 模塊.由于 node.js 中的請(qǐng)求本質(zhì)上是分塊的,尤其是長(zhǎng)請(qǐng)求,因此您無需更深入地了解協(xié)議即可實(shí)現(xiàn)相同的內(nèi)容.

      Node.js has a built in http module. Since requests are chunked by nature in node.js, especially long requests, you can implement the same thing without the more advanced understanding of the protocol.

      這次我們使用http模塊來創(chuàng)建一個(gè)http服務(wù)器

      This time, let's use the http module to create an http server

      server = http.createServer( function(req, res) { //create an HTTP server
          // The parameters are request/response objects
          // check if method is post, and the headers contain your value.
          // The connection was established but the body wasn't sent yet,
          // More information on how this works is in the above solution
          var specialRequest = (req.method == "POST") && req.headers["YourHeader"] === "YourTokenValue";
          if(specialRequest ){ // detect requests for special treatment
            // same as TCP direct solution add chunks
            req.on('data',function(chunkOfBody){
                    //handle a chunk of the message body
            });
          }else{
              res.end(); // abort the underlying TCP connection, since the request and response use the same TCP connection this will work
              //req.destroy() // destroy the request in a non-clean matter, probably not what you want.
          }
      }).listen(8080);
      

      這是基于這樣一個(gè)事實(shí),nodejs http 模塊中的 request 句柄在默認(rèn)情況下實(shí)際上是在發(fā)送標(biāo)頭后掛鉤的(但沒有執(zhí)行任何其他操作).(在服務(wù)器模塊中 , 這個(gè)在解析器模塊中)

      This is based on the fact the request handle in a nodejs http module actually hooks on after the headers were sent (but nothing else was performed) by default. (this in the server module , this in the parser module)

      用戶 igorw 建議使用 100 Continue 標(biāo)題假設(shè)您的目標(biāo)瀏覽器支持它.100 Continue 是一種狀態(tài)代碼,旨在完全按照您的意圖執(zhí)行:

      User igorw suggested a somewhat cleaner solution using the 100 Continue header assuming browsers you're targeting supports it. 100 Continue is a status code designed to do exactly what you're attempting to:

      100(繼續(xù))狀態(tài)(見第 10.1.1 節(jié))的目的是為了允許發(fā)送帶有請(qǐng)求正文的請(qǐng)求消息的客戶端確定源服務(wù)器是否愿意接受請(qǐng)求(基于請(qǐng)求頭)在客戶端發(fā)送請(qǐng)求之前身體.在某些情況下,它可能不合適或高度如果服務(wù)器拒絕,客戶端發(fā)送正文的效率低下不看正文的消息.

      The purpose of the 100 (Continue) status (see section 10.1.1) is to allow a client that is sending a request message with a request body to determine if the origin server is willing to accept the request (based on the request headers) before the client sends the request body. In some cases, it might either be inappropriate or highly inefficient for the client to send the body if the server will reject the message without looking at the body.

      這里是:

      var http = require('http');
       
      function handle(req, rep) {
          req.pipe(process.stdout); // pipe the request to the output stream for further handling
          req.on('end', function () {
              rep.end();
              console.log('');
          });
      }
       
      var server = new http.Server();
       
      server.on('checkContinue', function (req, rep) {
          if (!req.headers['x-foo']) {
              console.log('did not have foo');
              rep.writeHead(400);
              rep.end();
              return;
          }
       
          rep.writeContinue();
          handle(req, rep);
      });
       
      server.listen(8080);
      

      您可以在此處查看示例輸入/輸出.這將要求您使用適當(dāng)?shù)?Expect: 標(biāo)頭觸發(fā)請(qǐng)求.

      You can see sample input/output here. This would require your request to fire with the appropriate Expect: header.

      這篇關(guān)于通過 PHP 或 Apache 從服務(wù)器端上傳 HTTP 文件的文章就介紹到這了,希望我們推薦的答案對(duì)大家有所幫助,也希望大家多多支持html5模板網(wǎng)!

      【網(wǎng)站聲明】本站部分內(nèi)容來源于互聯(lián)網(wǎng),旨在幫助大家更快的解決問題,如果有圖片或者內(nèi)容侵犯了您的權(quán)益,請(qǐng)聯(lián)系我們刪除處理,感謝您的支持!

相關(guān)文檔推薦

Action View Helper in Zend - Work around?(Zend 中的動(dòng)作視圖助手 - 解決方法?)
Is this a good way to match URI to class/method in PHP for MVC(這是將 URI 與 PHP 中用于 MVC 的類/方法匹配的好方法嗎)
Where do I save partial (views) in Zend Framework, to be accessible for all Views in my App?(我在哪里保存 Zend Framework 中的部分(視圖),以便我的應(yīng)用程序中的所有視圖都可以訪問?) - IT屋-程序員軟件開發(fā)技術(shù)
Having a single entry point to a website. Bad? Good? Non-issue?(有一個(gè)網(wǎng)站的單一入口點(diǎn).壞的?好的?沒問題?)
Is MVC + Service Layer common in zend or PHP?(MVC + 服務(wù)層在 Zend 或 PHP 中常見嗎?)
Hello World example in MVC approach to PHP(PHP MVC 方法中的 Hello World 示例)
主站蜘蛛池模板: 久久久久久免费毛片精品 | 在线a视频 | 亚洲国产成人在线视频 | 午夜久久久久久久久久一区二区 | www.av在线| 中文字幕在线三区 | 一区二区国产精品 | 中文字幕 在线观看 | www在线视频 | 99久久婷婷国产综合精品电影 | 伊人婷婷 | 欧美一区二区三区在线播放 | 欧美日韩精品在线免费观看 | 日韩欧美在线观看 | 在线成人av | 午夜爽爽爽男女免费观看 | 欧美99久久精品乱码影视 | 亚洲网站观看 | 国产免费自拍 | 91精品久久久久久久久 | 日韩毛片在线观看 | 国产精品污www一区二区三区 | 日韩欧美精品在线 | 国产成人高清视频 | 华丽的挑战在线观看 | 伊人免费观看视频 | 国产日韩欧美激情 | 理论片午午伦夜理片影院 | 亚洲欧美日韩在线 | www.亚洲一区二区 | 亚洲精品久久久9婷婷中文字幕 | 亚洲综合在线播放 | 亚洲欧美国产精品一区二区 | 精品成人一区二区 | 久久69精品久久久久久久电影好 | 伊人网综合在线观看 | 国产精品国产a级 | 少妇久久久久 | 超级黄色一级片 | 成人不卡 | 91在线区 |