웹 애플리케이션에서는 파일 업로드 기능을 제공해야 하는 경우가 많습니다. 일반적인 시나리오에는 사용자 아바타 업로드, 앨범 사진 업로드 등이 포함됩니다. 업로드할 파일이 상대적으로 큰 경우 업로드 진행 상황을 보여주는 진행 표시줄을 제공해야 합니다.
PHP 5.4 이전에는 이러한 진행 표시줄을 구현하는 것이 쉽지 않았습니다. 크게 세 가지 방법이 있었습니다.
Flash, Java, ActiveX 사용
PHP의 APC 확장 사용
HTML5의 파일 API 사용
관련 학습 권장사항: 초보부터 숙련까지 PHP 프로그래밍
첫 번째 방법은 제3자 브라우저 플러그인을 사용하는데, 이는 충분히 다용도가 아니며 쉽게 보안 위험을 초래할 수 있습니다. 그러나 Flash의 광범위한 사용으로 인해 여전히 Flash를 솔루션으로 사용하는 웹사이트가 많이 있습니다.
두 번째 방법의 단점은 PHP의 APC 확장 라이브러리를 설치해야 하고 사용자가 서버 측 구성을 제어해야 한다는 것입니다. 또한 업로드 진행률 표시줄을 구현하기 위해 APC를 설치했다면 분명히 약간 과잉입니다.
세 번째 방법은 가장 이상적인 방법이어야 하며 서버 측 지원이 필요하지 않으며 브라우저 측에서만 Javascript를 사용합니다. 그러나 HTML5 표준이 아직 확립되지 않았고, 브라우저 제조사마다 지원하는 방식이 다르기 때문에 이 방법은 아직까지 대중화되기에는 어렵습니다.
PHP 5.4에 도입된 세션 기반 업로드 진행 모니터링 기능(session.upload_progress)은 서버 측 업로드 진행 모니터링 솔루션을 제공합니다. PHP 5.4로 업그레이드한 후에는 APC 확장을 설치할 필요가 없습니다. 기본 PHP 및 프런트엔드 Javascript만 사용하여 업로드 진행률 표시줄을 구현할 수 있습니다.
이제 PHP 5.4의 새로운 session.upload_progress 기능을 자세히 소개하겠습니다.
원칙 소개
브라우저가 서버에 파일을 업로드하면 PHP는 파일 업로드에 대한 자세한 정보(예: 업로드 시간, 업로드 진행률 등)를 세션에 저장합니다. 그런 다음 업로드가 진행됨에 따라 세션의 정보가 주기적으로 업데이트됩니다. 이러한 방식으로 브라우저는 Ajax를 사용하여 주기적으로 서버 측 스크립트를 요청할 수 있으며 스크립트는 세션에서 진행률 정보를 반환합니다. 브라우저 측 Javascript는 이 정보를 기반으로 진행률 표시줄을 표시/업데이트할 수 있습니다.
그럼 파일 업로드 정보는 어떻게 저장되나요? 어떻게 접근하나요? 아래에서 자세히 설명드리겠습니다.
PHP 5.4에는 일부 구성 항목이 도입되었습니다(php.ini에 설정됨)
코드는 다음과 같습니다.
session.upload_progress.enabled = "1" session.upload_progress.cleanup = "1" session.upload_progress.prefix = "upload_progress_" session.upload_progress.name = "PHP_SESSION_UPLOAD_PROGRESS" session.upload_progress.freq = "1%" session.upload_progress.min_freq = "1"
그 중 활성화는 기본적으로 켜져 있는 upload_progress 기능을 켤지 여부를 제어합니다. 이후 파일 업로드 요청 시 세션 관련 정보 삭제 여부가 기본적으로 활성화됩니다.
접두사 및 이름은 세션에서 진행 정보가 저장되는 변수 이름/키 이름을 설정하는 데 사용됩니다. 이 두 항목의 자세한 사용법은 아래를 참조하세요.
freq 및 min_freq는 서버 측에서 진행 정보 업데이트 빈도를 설정하는 데 사용됩니다. 이 두 항목을 적절하게 설정하면 서버의 부하를 줄일 수 있습니다.
파일 업로드 양식에서 이 업로드에 대한 식별자를 설정하고 이 식별자를 사용하여 후속 프로세스에서 진행 정보를 참조해야 합니다. 특히, 업로드 양식에는 숨겨진 입력이 있어야 하며, 해당 이름 속성은 php.ini의 session.upload_progress.name 값이며, 해당 값은 사용자가 정의한 식별자입니다.
코드는 다음과 같습니다.
<input type="hidden" name="<?php echo ini_get('session.upload_progress.name'); ?>" value="test" />
파일 업로드 양식을 받은 후 PHP는 $_SESSION 변수에 새 키를 생성합니다. 키 이름은 사용자 정의 식별자와 연결된 session.upload_progress.prefix 값입니다. 위와 같이 얻은 문자열을 얻을 수 있습니다.
코드는 다음과 같습니다.
$name = ini_get('session.upload_progress.name'); $key = ini_get('session.upload_progress.prefix') . $_POST[$name]; $_SESSION[$key]; // 这里就是此次文件上传的进度信息了
$_SESSION[$key]
이 변수의 구조는 다음과 같습니다.$_SESSION[$key]
这个变量的结构是这样的:
代码如下:
$_SESSION["upload_progress_test"] = array( "start_time" => 1234567890, // 开始时间 "content_length" => 57343257, // POST请求的总数据长度 "bytes_processed" => 453489, // 已收到的数据长度 "done" => false, // 请求是否完成 true表示完成,false未完成 // 单个文件的信息 "files" => array( 0 => array( ... ), // 同一请求中可包含多个文件 1 => array( ... ), ) );
这样,我们就可以使用其中的 content_length 和 bytes_processed 两项来得到进度百分比。
程序示例
原理介绍完了,下面我们来完整的实现一个基于PHP和Javascript的文件上传进度条。
上传表单
首先,来编写我们的上传表单页面 index.php,代码如下:
代码如下:
<form id="upload-form" action="upload.php" method="POST" enctype="multipart/form-data" style="margin:15px 0" target="hidden_iframe"> <input type="hidden" name="" value="test" /> <p><input type="file" name="file1" /></p> <p><input type="submit" value="Upload" /></p> </form> <iframe id="hidden_iframe" name="hidden_iframe" src="about:blank" style="display:none;"></iframe> <p id="progress" class="progress" style="margin-bottom:15px;display:none;"> <p class="bar" style="width:0%;"></p> <p class="label">0%</p> </p>
注意表单中的session.upload_progress.name隐藏项,值设置为了test。表单中仅有一个文件上传input,如果需要,你可以添加多个。
这里需要特别注意一下表单的target属性,这里设置指向了一个当前页面中的iframe。这一点很关键,通过设置target属性,让表单提交后的页面显示在iframe中,从而避免当前的页面跳转。因为我们还得在当前页面显示进度条呢。
#progress
if(is_uploaded_file($_FILES['file1']['tmp_name'])){ move_uploaded_file($_FILES['file1']['tmp_name'], "./{$_FILES['file1']['name']}"); } ?>이런 방식으로 content_length와 bytes_processed 두 항목을 사용하여 진행률을 얻을 수 있습니다.
프로그램 예제
이제 원리가 소개되었으니 PHP와 Javascript 기반의 파일 업로드 진행 표시줄을 완벽하게 구현해 보겠습니다.
session_start(); $i = ini_get('session.upload_progress.name'); $key = ini_get("session.upload_progress.prefix") . $_GET[$i]; if (!empty($_SESSION[$key])) { $current = $_SESSION[$key]["bytes_processed"]; $total = $_SESSION[$key]["content_length"]; echo $current < $total ? ceil($current / $total * 100) : 100; }else{ echo 100; } ?>🎜숨겨진 항목 session.upload_progress.name에 주의하세요. form이고 값은 test로 설정됩니다. 양식에는 파일 업로드 입력이 하나만 있으며 필요한 경우 여러 개를 추가할 수 있습니다. 🎜🎜양식의 대상 속성에 특별한 주의가 필요합니다. 여기 설정은 현재 페이지의 iframe을 가리킵니다. 이는 target 속성을 설정함으로써 양식이 제출된 후의 페이지가 iframe에 표시되므로 현재 페이지 이동을 방지하는 데 중요합니다. 현재 페이지에 진행률 표시줄을 표시해야 하기 때문입니다. 🎜🎜
#progress
이 p는 진행률 표시줄을 표시하는 데 사용됩니다. 🎜🎜참고: index.php 시작 부분에 session_start()를 추가하는 것을 잊지 마세요. 🎜🎜🎜업로드된 파일 처리🎜🎜🎜양식의 작업은 upload.php를 가리킵니다. upload.php에서 업로드된 파일을 처리하고 현재 디렉터리로 전송합니다. 여기에는 일반적인 업로드 처리와 차이가 없습니다. 🎜🎜代码如下:
if(is_uploaded_file($_FILES['file1']['tmp_name'])){ move_uploaded_file($_FILES['file1']['tmp_name'], "./{$_FILES['file1']['name']}"); } ?>
Ajax获取进度信息
这一步是关键,我们需要建立一个 progress.php 文件,用来读取session中的进度信息; 然后我们在 index.php 中增加Javascript代码,向 progress.php 发起Ajax请求,然后根据获得的进度信息更新进度条。
progress.php 的代码如下:
代码如下:
session_start(); $i = ini_get('session.upload_progress.name'); $key = ini_get("session.upload_progress.prefix") . $_GET[$i]; if (!empty($_SESSION[$key])) { $current = $_SESSION[$key]["bytes_processed"]; $total = $_SESSION[$key]["content_length"]; echo $current < $total ? ceil($current / $total * 100) : 100; }else{ echo 100; } ?>
在这里我们获得$_SESSION变量中的进度信息,然后输出一个进度百分比。
在 index.php 中,我们将如下代码添加到页面底部 (为简便,这里使用jQuery):
代码如下:
function fetch_progress(){ $.get('progress.php',{ '' : 'test'}, function(data){ var progress = parseInt(data); $('#progress .label').html(progress + '%'); $('#progress .bar').css('width', progress + '%'); if(progress < 100){ setTimeout('fetch_progress()', 100); }else{ $('#progress .label').html('完成!'); } }, 'html'); } $('#upload-form').submit(function(){ $('#progress').show(); setTimeout('fetch_progress()', 100); });
当#upload-form被提交时,我们把进度条显示出来,然后反复调用 fetch_progress() 获得进度信息,并更新进度条,直到文件上传完毕,显示'完成!'。
注意事项
input标签的位置
name为session.upload_progress.name的input标签一定要放在文件input 73fb0a88f70dfc104fc3e769bdf0b422 的前面。
取消上传
通过设置 $_SESSION[$key]['cancel_upload'] = true 可取消当次上传。但仅能取消正在上传的文件和尚未开始的文件。已经上传成功的文件不会被删除。
setTimeout vs. setInterval
应该通过 setTimeout() 来调用 fetch_progress(),这样可以确保一次请求返回之后才开始下一次请求。如果使用 setInterval() 则不能保证这一点,有可能导致进度条出现'不进反退'。
위 내용은 세션 및 Javascript를 사용하여 PHP에서 파일 업로드 진행률 표시줄 기능을 구현하는 방법을 알아보세요.의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!