PHP大ファイル操作
37238 ワード
ファイルスライスアップロード
jsのBlobオブジェクトFormDataオブジェクトを使用すると、大きなファイルのスライスアップロード機能を実現できます.BlobとFormDataの具体的な使用方法については、次のアドレスでFormDataオブジェクトの使用Blobオブジェクトの使用を確認できます.
以下は実装コードであり、この例ではバックエンドコードはphpを使用して実装されるが、基本機能を示すだけで、具体的なファイル検証ロジックは先に無視される.前段コード:
バックエンドphpコード:
ブレークポイント
ブラウザを閉じるか、ネットワークを切断すると、アップロードファイル名、アップロードファイルサイズをローカルwindowに格納できます.localStorage.getItem、ファイルをアップロードするときに同名のファイルとアップロードされたサイズをクエリーします.個人的な考え方、テストされていません.
大ファイルのリモートダウンロード
PHP読み出し指定バイトダウンロード
PHP curlブロックダウンロード、コアはcurl_setopt($ch, CURLOPT_RANGE, $range)
PHPが大きなファイルを読み込む
yield反復器を用いて実現し、反復器原理PHP yield生成器
SplFileObject指定行ファイルの内容を読み込む
一般的にファイルを読み込むにはfopenまたはfileを使います.get_contentsは、前者はループ読み出し可能で、後者は一括読み出し可能ですが、ファイルの内容を一括ロードして操作します.現在のファイルは数百Mb,数Gでは性能が低下し,SplFileObjectは大きなファイルに対する処理のクラスである.
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,''
}