PHP大ファイル操作

37238 ワード

ファイルスライスアップロード
jsのBlobオブジェクトFormDataオブジェクトを使用すると、大きなファイルのスライスアップロード機能を実現できます.BlobとFormDataの具体的な使用方法については、次のアドレスでFormDataオブジェクトの使用Blobオブジェクトの使用を確認できます.
以下は実装コードであり、この例ではバックエンドコードはphpを使用して実装されるが、基本機能を示すだけで、具体的なファイル検証ロジックは先に無視される.前段コード:
DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>uploadtitle>
    <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js">script>
head>
<body>
    <input type="file" name="file" id="file">
    <button id="upload" onClick="upload()">uploadbutton>
    <script type="text/javascript">
        var bytesPerPiece = 1024 * 1024; //           1MB .
        var totalPieces;
        //    
        function upload() {
            var blob = document.getElementById("file").files[0];
            var start = 0;
            var end;
            var index = 0;
            var filesize = blob.size;
            var filename = blob.name;

            //        
            totalPieces = Math.ceil(filesize / bytesPerPiece);
            while(start < filesize) {
                end = start + bytesPerPiece;
                if(end > filesize) {
                    end = filesize;
                }

                var chunk = blob.slice(start,end);//        
                var sliceIndex= blob.name + index;
                var formData = new FormData();
                formData.append("file", chunk, filename);
                $.ajax({
                    url: 'http://localhost:9999/test.php',
                    type: 'POST',
                    cache: false,
                    data: formData,
                    processData: false, //            
                    contentType: false, //   JQuery     ,       ,             
                }).done(function(res){ //    

                }).fail(function(res) {  //    

                });
                start = end;
                index++;
            }
        }
    script>
body>
html>

バックエンドphpコード:
php
header('Access-Control-Allow-Origin:*');
header("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept");

$file = $_FILES['file'];
$filename = $file['name'];
file_put_contents($filename, file_get_contents($file['tmp_name']), FILE_APPEND);

ブレークポイント
ブラウザを閉じるか、ネットワークを切断すると、アップロードファイル名、アップロードファイルサイズをローカルwindowに格納できます.localStorage.getItem、ファイルをアップロードするときに同名のファイルとアップロードされたサイズをクエリーします.個人的な考え方、テストされていません.
 
大ファイルのリモートダウンロード
PHP読み出し指定バイトダウンロード
php
set_time_limit(0);

$read_file="https://github.com/tommy-muehle/puppet-vagrant-boxes/releases/download/1.1.0/centos-7.0-x86_64.box";
$write_file="centos-7.0-x86_64.box";
$host_file = fopen($read_file, 'r');
$fh = fopen($write_file, 'w');
 
while (!feof($host_file )) {
    $output = fread($host_file , 8192); //
    fwrite($fh, $output);
}
 
fclose($host_file );
fclose($fh);

PHP curlブロックダウンロード、コアはcurl_setopt($ch, CURLOPT_RANGE, $range)
/**
 *        Key  
 * @param string $key header  key
 * @param string $responseHead header    
 * @return string
 */
private function getResHeaderValue($key, $responseHead)
{
    $value = '';
    $headArr = explode("\r
", $responseHead); foreach ($headArr as $loop) { if ($key == 'Http-Code') { if (preg_match('/HTTP\/1\.[0-9]{1} ([0-9]{3})/', $loop, $matches)) { return $matches['1']; } } else { if (strpos($loop, $key) !== false) { $value = trim(str_replace($key . ':', '', $loop)); } } } return $value; }

private $siteUrl='';//
/** * * @return array * @throws Exception */ private function getSiteFiLeInfo($file_url) { $responseHeader = get_headers($file_url, 1); if (!$responseHeader) { throw new Exception(' !'); } if (!empty($responseHeader['Location'])) { // 302 $this->siteUrl = $responseHeader['Location']; return $this->getSiteFiLeInfo(); } return $responseHeader; } /** * * @param string $fileName * @throws */ public function saveFile($fileName) { // $siteFileInfo = $this->getSiteFiLeInfo(); $siteFileLength = $siteFileInfo['Content-Length'] ?? 0; // $fd = null; if (file_exists($fileName)) { $fd = fopen($fileName, 'ab'); } else { $fd = fopen($fileName, 'wb'); } if (!$fd) { throw new Exception(' !'); } // , if (!flock($fd, LOCK_EX | LOCK_NB)) { throw new Exception(' !'); } // $fileSize = filesize($fileName); if ($fileSize && $fileSize >= $siteFileLength) { throw new Exception(' , !'); } // $burstBytes=1024; $sByte = $fileSize; $eByte = $sByte + $burstBytes; // while (true) { // if ($fileSize >= $siteFileLength) { fclose($fd); break; } // $xRange = "{$sByte}-$eByte"; // curl $result = $this->curl($xRange); // $code = $result['code'] ?? 0; if (!$code) { throw new Exception('Http !'); } if ($code != 206) { throw new Exception('Http , !'); } // $streamLength = $result['length'] ?? 0; // $streamContent = $result['stream'] ?? ''; if ($streamLength > 0) { file_put_contents('log.txt', $xRange . PHP_EOL, FILE_APPEND); $saveRes = fwrite($fd, $streamContent); if (!$saveRes) { throw new Exception(' !'); } if ($saveRes != $streamLength) { // , , , throw new Exception(' : !'); } // range $sByte = $eByte + 1; $eByte = $sByte + $burstBytes; // $fileSize = $fileSize + $saveRes; } } } /** * * @param string $range * @param array $header Http * @return array * @throws */ private function curl($range, $header = []) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $this->siteUrl); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET'); curl_setopt($ch, CURLOPT_HEADER, TRUE); // SSL curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); // curl_setopt($ch, CURLOPT_RANGE, $range); // x-y, 。 ”X-Y” ,X Y ( ) 。HTTP , (X-Y,N-M)。 // header if ($header) { curl_setopt($ch, CURLOPT_HTTPHEADER, $header); } // $response = curl_exec($ch); if (curl_errno($ch)) { throw new Exception(' :' . curl_error($ch)); } // response_header response_body $headSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE); $httpHeader = substr($response, 0, $headSize); if (!$httpHeader) { throw new Exception(' : '); } $fileStream = substr($response, $headSize); // header $length = $this->getResHeaderValue('Content-Length', $httpHeader); $httpCode = $this->getResHeaderValue('Http-Code', $httpHeader); curl_close($ch); // return [ 'code' => $httpCode, 'length' => $length, 'stream' => $fileStream, ]; }

  
PHPが大きなファイルを読み込む
yield反復器を用いて実現し、反復器原理PHP yield生成器
//    yield      
function readYieldFile($fileName)
{
  $handle = fopen($fileName, 'r');
  while (!feof($handle)) {
      yield fgets($handle);
  }
  fclose($handle);
}

$lines = readYieldFile('./all.txt');
foreach ($lines as $row) {
   file_put_contens('test.txt',$row,FILE_APPEND); 
}

SplFileObject指定行ファイルの内容を読み込む
一般的にファイルを読み込むにはfopenまたはfileを使います.get_contentsは、前者はループ読み出し可能で、後者は一括読み出し可能ですが、ファイルの内容を一括ロードして操作します.現在のファイルは数百Mb,数Gでは性能が低下し,SplFileObjectは大きなファイルに対する処理のクラスである.
/**      X  Y    (  php5、php4)  
 * @param string $filename    
 * @param int $startLine      
 * @param int $endLine      
 * @return string
 */
function getFileLines($filename, $startLine = 1, $endLine=50, $method='rb') {
    $content = array();
    $count = $endLine - $startLine;  

    $fp = new SplFileObject($filename, $method);
    $fp->seek($startLine-1);//    N , seek     0    
    for($i = 0; $i <= $count; ++$i) {
         $content[]=$fp->current();// current()       
         $fp->next();//    
    }

    return array_filter($content); // array_filter  :false,null,''
}