모바일 인터넷 시대가 도래하면서 대용량 파일을 전송해야 하는 필요성이 점점 더 일반화되고 있습니다. 그 중 널리 사용되는 프로그래밍 언어인 PHP는 대용량 파일을 업로드하고 다운로드하는 데 좋은 성능을 발휘합니다. 이 기사에서는 대용량 파일, 청크 업로드, 재개된 업로드 및 비동기 다운로드를 처리하는 방법과 같은 중요한 기술을 포함하여 PHP의 대용량 파일 업로드 및 다운로드 기술을 학습합니다.
1. PHP에서 대용량 파일을 처리하는 방법
PHP에서 대용량 파일을 처리할 때 가장 중요한 단계는 적절한 메모리 사용 계획을 세우는 것입니다. 전체 대용량 파일을 메모리로 직접 읽을 수는 없습니다. 이로 인해 메모리 오버플로가 발생하고 전체 프로그램이 중단될 수 있기 때문입니다. 그렇다면 PHP에서 대용량 파일을 처리하는 방법은 무엇입니까?
우선, 이 문제를 해결하기 위해 "파일 포인터" 개념을 사용할 수 있습니다. "파일 포인터"는 전체 파일을 한 번에 읽는 대신 파일의 특정 부분을 읽을 수 있는 파일에 있는 포인터입니다. PHP에서는 fopen() 및 fread() 함수를 사용하여 파일을 열고 읽을 수 있습니다.
두 번째로 "스트리밍" 방법을 사용할 수 있습니다. 먼저 대용량 파일을 여러 부분으로 분할한 다음 하나씩 업로드하거나 다운로드하세요. 이렇게 하면 전체 대용량 파일을 한 번에 읽는 것을 방지하고 데이터 무결성을 보장할 수 있습니다.
2. 대용량 파일 업로드
HTTP 통신의 경우 PHP의 기본 업로드 파일 크기는 2MB이므로 더 큰 파일을 업로드할 수 있도록 php.ini 구성 파일에서 upload_max_filesize 옵션을 변경해야 합니다.
하지만 php.ini 파일을 변경한 후에도 대용량 파일을 업로드하는 데 여전히 문제가 발생합니다. 업로드 중 메모리 누수 및 프로그램 충돌을 방지하려면 어떻게 해야 합니까? 대답은 청크 업로드 기술을 사용하는 것입니다.
청크 업로드는 대용량 파일을 고정된 크기의 청크로 나눈 후 업로드가 완료될 때까지 하나씩 업로드하는 것입니다. 이 방법은 전체 파일을 한 번에 읽는 것을 방지하고 서버 메모리 압박을 줄입니다.
구체적인 구현은 다음과 같습니다.
프런트엔드 코드:
<input type="file" name="file" id="file">
var chunkSize = 1 * 1024 * 1024; //每一块的大小为1MB var file = document.getElementById('file').files[0]; var name = file.name; var size = file.size; var chunkNum = Math.ceil(size / chunkSize); //总块数 for(var i=0;i<chunkNum;i++){ var start = i*chunkSize; var end = Math.min(size,start+chunkSize); var chunk = file.slice(start,end); //将文件切成每个chunkSize大小的块 //使用FormData上传 var formData = new FormData(); formData.append('chunk', chunk); formData.append('filename', i+'_'+name); //在文件名前加上块的编号 //发起已经分割好的块的上传请求 send(chunkUrl,formData); }
백엔드 코드:
$chunk = $_FILES['chunk']; //获取文件块 $filename = $_POST['filename']; //获取文件名 //上传文件块 move_uploaded_file( $chunk['tmp_name'] , $upload.$filename); echo "success";
위 코드는 대용량 파일을 여러 개의 1MB 블록으로 나누어 업로드함으로써 부담을 분산시키는 구현입니다.
주의할 만한 또 다른 문제는 대용량 파일의 업로드가 실수로 취소된 경우 중단된 위치에서 어떻게 계속 업로드할 수 있다는 것입니다.
답은 중단점 재개 기술을 사용하는 것입니다. 파일을 업로드하는 동안 파일 업로드 진행 상황을 기록한 다음 사용자가 다시 업로드할 때 마지막 업로드의 완료되지 않은 파일 블록을 캐시하여 나중에 다시 업로드할 수 있습니다.
구체적인 구현은 다음과 같습니다.
프런트엔드 코드:
var chunkSize = 1 * 1024 * 1024; //每一块的大小为1MB var file = document.getElementById('file').files[0]; var name = file.name; var size = file.size; var chunkNum = Math.ceil(size / chunkSize); //总块数 for(var i=0;i<chunkNum;i++){ var start = i*chunkSize; var end = Math.min(size,start+chunkSize); var chunk = file.slice(start,end); //将文件切成每个chunkSize大小的块 //使用FormData上传 var formData = new FormData(); formData.append('chunk', chunk); formData.append('filename', i+'_'+name); //在文件名前加上块的编号 formData.append('chunkNum',chunkNum); //总块数 formData.append('index',i); //当前块的编号 //将文件分块上传 send(chunkUrl,formData,function(){ uploaded[i] = 1; //标记该块已上传 var uploadedAll = uploaded.every(v => v == 1); //检查是否所有块都已上传 //如果所有块都已上传,则在服务端组装文件 if(uploadedAll){ var formData = new FormData(); formData.append('name', name); formData.append('chunkNum',chunkNum); //总块数 //发起文件组装请求 send(mergeUrl,formData,function(response){ console.log(response); }); } }); }
백엔드 코드:
$chunk = $_FILES['chunk']; //获取文件块 $filename = $_POST['filename']; //获取文件名 $chunkNum = $_POST['chunkNum']; //获取文件总块数 $index = $_POST['index']; //获取当前块的编号 //上传文件块 move_uploaded_file( $chunk['tmp_name'] , $upload.$filename); //上传完成后检查所有块是否已上传 $uploaded = $this->isUploaded($upload,$chunkNum); if($uploaded){ $this->mergeFile($upload,$chunkNum,$name); //组装文件 } echo "success";
위 코드는 파일 업로드를 부분적으로 구현하고 클라이언트에서 업로드 진행 상황을 표시하며 업로드가 완료되었는지 확인합니다. 서버에서 완료되었습니다. 업로드가 완료되면 업로드된 모든 파일 청크가 연결됩니다.
3. 대용량 파일 다운로드
PHP에서 대용량 파일을 다운로드할 때 메모리 누수 및 프로그램 충돌 문제도 해결해야 합니다. 이를 위해 비동기 다운로드 기술을 사용할 수 있습니다.
비동기 다운로드는 서버의 메인 스레드를 차단하지 않도록 다운로드 요청을 별도의 스레드에 배치하는 것을 의미합니다. PHP에서는 exec() 함수를 사용하여 별도의 스레드를 시작할 수 있습니다.
구체적인 구현은 다음과 같습니다.
프런트엔드 코드:
<a href="#" onclick="download()">下载</a>
function download(){ var filename = 'test.zip'; //准备下载文件名 //发起异步下载请求 var ajax = new XMLHttpRequest(); ajax.open('GET', '/download.php?filename='+filename, true); ajax.send(); }
백엔드 코드:
$action = isset($_GET['action']) ? $_GET['action'] : 'download'; //获取下载动作 $filename = $_GET['filename']; //获取文件名 if($action == 'download'){ //启动异步下载 exec('php download.php '.$filename.' > /dev/null &'); }else{ //文件下载 header("Content-type: application/octet-stream"); header("Content-Disposition: attachment; filename=".$filename); header("Accept-Ranges: bytes"); $file = fopen($download.$filename,"r"); if($file){ while(!feof($file)){ print(fread($file, 1024*8 )); flush(); ob_flush(); } } fclose($file); }
위 코드는 클라이언트에서 비동기 다운로드 요청을 구현하고, 백엔드는 exec() 함수를 사용하여 시작합니다. 다운로드 작업을 위한 별도의 스레드를 사용하여 메인 스레드가 차단되는 문제를 해결합니다. 동시에 청크 다운로드 및 버퍼에 출력을 사용하여 파일을 다운로드할 때 메모리 문제도 해결됩니다.
4. 요약
이 기사에서는 주로 대용량 파일 처리 방법, 청크 업로드, 중단점 재개 및 비동기 다운로드 기술을 포함하여 PHP의 대용량 파일 업로드 및 다운로드 기술을 배웠습니다. 이 기사의 가이드를 통해 우리는 PHP에서 대용량 파일을 처리하는 기술을 더 잘 익힐 수 있으며 이러한 기술을 실제 프로젝트에 적용하여 대용량 파일을 효율적으로 전송할 수 있습니다.
위 내용은 PHP에서 대용량 파일 업로드 및 다운로드에 대한 기술 가이드의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!