수년 동안 웹 개발자를 괴롭혀온 문제는 파일 업로드 진행률 표시줄과 같은 실시간 정보를 애플리케이션에 추가하는 방법입니다. 사용자는 참을성이 없고, 브라우저가 무언가를 수행하는 동안 가만히 앉아 기다리기를 원하지 않으며, 브라우저가 정지되었는지 또는 연결 속도가 느린지 궁금해합니다. 사용자에게 유용한 정보를 제공하고 진행 상황을 정확하게 알려주는 진행률 표시기를 제공합니다.
처음에는 먼저 사용자 컴퓨터에서 파일 크기를 가져온 다음 파일이 Completed에 업로드되는 디렉터리에 대해 몇 가지 간단한 계산을 수행하면 쉽게 수행할 수 있다고 생각할 수도 있습니다. 섬기는 사람. 두 번째 생각에 관해서, 당신은 일이 당신이 생각하는 것만큼 간단하지 않다는 것을 알게 될 것입니다.
JavaScript는 파일 이름, 유형은 물론 기본 이미지의 너비와 높이에도 액세스할 수 있지만 HTML5가 되어서야 파일 크기에 액세스할 수 있었습니다. 불행하게도 HTML5는 아직 완성되지 않은 표준이며 모든 브라우저에서 균일하게 지원되지 않습니다. 또 다른 해결책은 설치된 Flash, Java 또는 ActiveX 플러그인을 사용하는 것입니다. 괜찮습니다. 전달하겠습니다. 또 다른 해결책은 선택적 PHP 캐싱 확장을 설치하는 것입니다. 하지만 호스팅 환경에 따라 사용하지 못할 수도 있습니다. 이는 이와 같은 작은 작업에는 약간 과도한 것처럼 보입니다.
옵션이 다 귀찮고 미션이 금방 골치 아픈 것 같아요. 하지만 요다의 말처럼 "없다...하나 있다."
제가 PHP를 좋아하는 많은 이유 중 하나는 겉보기에 어려운 작업을 매우 쉽게 만들어준다는 것입니다. PHP 5.4에서는 새로운 구성 옵션 세트를 사용하여 session.upload_progress를 다시 수행했습니다.
이 기사에서는 이 기능을 사용하여 외부 라이브러리나 브라우저 종속성 없이 간단한 업로드 진행률 표시줄을 만드는 방법을 보여 드리겠습니다. 먼저 작동 방식에 대해 논의한 다음 작업을 완료하는 데 필요한 네 가지 파일(업로드 양식, 일부 JavaScript, 약간의 CSS 및 파일 반환 로드 상태)을 만드는 과정을 안내하겠습니다.
업로드 진행 상황 회의
파일 업로드를 허용하기 위한 일반적인 요구 사항 외에도 진행 상황을 추적할 수 있는 두 가지 요구 사항이 더 있습니다. session.upload_progress.enabled 지시문을 활성화해야 하며, session.upload_progress.name 지시문에 의해 지정된 이름을 가진 웹 양식에 숨겨진 필드가 있어야 합니다. session.upload_progress.enabled가 true이고(PHP 5.4 및 그 이후 버전에서 기본적으로) $_POST[session.upload_progress.name]이 파일 전송 업로드와 관련하여 $_SESSION 슈퍼 전역에서 사용 가능한 경우 배열입니다.
print_r()의 $_SESSION 배열 출력은 파일 전송 중 다음과 유사합니다.
Array ( [upload_progress_myForm] => Array ( [START_TIME] => 1323733740 [CONTENT_LENGTH] = > 721127769 [bytes_processed] => 263178326 [완료] => [파일] =>Array ( [0] =>Array ( [FIELD_NAME] => USERFILE [이름] => ubuntu-10.04.3 -Desktop i386.iso [tmp_name 값] => [오류] => 0 [완료] => [START_TIME] => 1323733740 [bytes_processed] => 263178026 ) ) ) )
때 로컬 또는 빠른 네트워크에서 개발 중이고 작은 파일을 업로드하는 경우 전송이 너무 빨리 이루어지기 때문에 진행 상황을 시각적으로 관찰할 수 없습니다. 이 경우 대용량 파일을 전송해 볼 수 있습니다. 더 큰 업로드, 특히 post_max_size 및 upload_max_filesize 지시문을 허용하도록 php.ini 파일을 설정했는지 확인한 다음 프로덕션으로 이동할 때 해당 값이 올바른 값인지 확인하십시오.
양식 만들기
첫 번째로 다룰 파일은 업로드 양식입니다. 최대한 단순하게 유지하기 위해 이 예제는 한 번에 하나의 파일 업로드만 처리할 수 있도록 게시됩니다. 또한 파일을 업로드한 후에는 파일을 저장하지 않을 것입니다.
form.php 코드는 다음과 같습니다.
<?PHP 如果($ _SERVER [ “REQUEST_METHOD” ] == “POST” &&!空($ _FILES [ “userfile的” ])){ / / move_uploaded_file()以 } ?> <HTML> <HEAD> <TITLE>文件上传进度条</ TITLE> <链接相对= “样式表” 类型= “文/ CSS” HREF = “style.css文件” > </ HEAD> <BODY> <分区编号= “bar_blank” > <分区编号= “bar_color” > </ DIV> </ DIV> <分区编号= “状态” > </ DIV> <形式的行动= “<PHP的回声$ _SERVER?[” PHP_SELF “];?>” 方法= “POST” ID = “myForm的” 是enctype = “多部分/窗体的数据” 目标= “hidden_iframe” > <输入类型= “隐藏” 值= “myForm的” 名称= “<?PHP的回声ini_get(” session.upload_progress.name ?“);>” > <输入类型= “文件” 名称= “USERFILE” > <BR> <输入类型= “提交” 值= “开始上传” > </ FORM> <iframe的ID = “hidden_iframe” 名称= “hidden_iframe” SRC = “关于:空白” > </ IFRAME> <脚本类型= “文/ JavaScript的” SRC = “的script.js” > </ SCRIPT> </ BODY> </ HTML>
이 예에서는 실제로 파일을 처리하는 코드가 생략되었습니다. 일이 단순해지도록 하세요. 이러한 코드가 어떻게 생겼는지에 관심이 있다면 Timothy Boronczyk의 PHP를 사용한 파일 업로드 기사를 확인하세요. 페이지 제목을 제공하고 스타일시트를 포함하는
헤더 섹션 뒤에는 작은 div 요소 모음이 있습니다. ID가 "bar_blank"인 DIV는 컨테이너의 진행률 표시줄입니다. ID가 "bar_color"인 div는 파일 업로드 진행 상황을 동적으로 업데이트합니다. '상태' div에는 업로드된 값의 비율이 표시됩니다.
该窗体设置为提交给同一个URL,并将其目标属性指向一个隐藏的iframe元素。 提交表单到一个隐藏的框架可以让你保持访问者在同一页上,而工作在后台正在做。 其实,这是一种常见的做法做“的Ajax文件上传”的时候,因为它是不可能直接发送使用JavaScript的一个文件的内容XmlHttpRequest对象。
在表格中,特殊的隐藏字段需要填充$_SESSION数组,接着出现一个文件上传输入和提交按钮。 提交表单将触发一个名为JavaScript函数startUpload()将被包含的JavaScript文件中定义。
在页面的底部是隐藏的框架,其形式将发布和进口script.js文件。
添加一些样式
下一个文件, style.css ,是相当直接的。 我定义的进度条容器的大小并给予它一个1px的黑色边框,进度条的颜色,因为它的加载,无论是IFRAME和进度条是隐藏的。
#bar_blank { 边界:固体1px的#000 ; 高度:20像素; 宽度:300像素; } #bar_color { 背景色:#006666 ; 高度:20像素; 宽度:0PX ; } #bar_blank,#hidden_iframe { 显示:无; }
客户端功能
该script.js文件是最大的组文件。 它包含六大功能,我将在下面讨论。 很多人喜欢用jQuery来提供一些功能在这里,你当然可以这样做,如果你愿意的话,但我个人更喜欢老派的做法。 类似于如何日本人放在手工制作的货物价值较高的,我只是觉得更热衷于代码,如果是我自己。
功能toggleBarVisibility(){ 变种E =的document.getElementById(“bar_blank” ); e.style.display =(e.style.display == “块” ?) “ 无” :“块” ; } 功能createRequestObject(){ 变种的http; 如果(navigator.appName == “Microsoft Internet Explorer的” ){ HTTP = 新的ActiveXObject(“Microsoft.XMLHTTP” ); } 否则{ HTTP = 新的XMLHttpRequest(); } 返回的http; } 功能sendRequest将(){ 变种的http = createRequestObject(); http.open(“GET” ,“progress.php” ); http.onreadystatechange = 函数(){用handleResponse(HTTP);}; http.send(空); } 功能用handleResponse(HTTP){ 无功响应; 如果(http.readyState == 4){ 响应= http.responseText; 的document.getElementById(“bar_color” 。)共0则回应+ “%” ; 的document.getElementById( “ 地位” 。)的innerHTML =响应+ “%” ; 如果(响应<100){ 的setTimeout(“sendRequest将()” ,1000); } 否则{ toggleBarVisibility(); 的document.getElementById( “ 地位” 。)的innerHTML = “Done(完成)。” ; } } } 功能startUpload(){ toggleBarVisibility(); 的setTimeout(“sendRequest将()” ,1000); } (函数(){ 的document.getElementById(“myForm会” )的onsubmit = startUpload; })();
该toggleBarVisibility()函数上的“bar_blank”的div根据需要显示或隐藏进度条设置合适的样式。 最初,它开始时隐藏,但会一次上传开始出现,然后再次隐藏当上载完成。
该createRequestObject()函数创建一个XMLHttpRequest或ActiveXObject根据用户的浏览器对象。 这可能是该功能大多数人都期待的jQuery或其他一些JavaScript框架来提供。
该sendRequest()函数请求progress.php文件与一个GET请求,然后调用handleResponse()函数来处理返回的数据。
该handleResponse()函数处理从响应progress.php这将是依赖于文件上传进度多项1-100之间。 我也更新了“状态”的div适当的值。 如果电流的百分比低于100然后调用JavaScript的原生setTimeout()函数来1秒后发送的更新另一个请求(你可能需要调整该值如适用),否则我再次隐藏进度条和状态设置为“完成”。
该startUpload()函数使得载栏可见,并发送一个更新请求的1秒的延迟。 这个小的延迟是必要的,为了给上传时间才能启动。
最后一个功能是一个自执行的匿名函数,它注册startUpload()与表单的提交事件。
实时进展
带来一切融合在一起的最后一个文件是progress.php文件:
<?PHP 在session_start(); 美元的关键= ini_get (“session.upload_progress.prefix” )。“myForm的” ; 如果(!空($ _SESSION [ $关键])){ $电流= $ _SESSION [ $关键] [ “bytes_processed” ]; 共$ = $ _SESSION [ $关键] [ “CONTENT_LENGTH” ]; 回声$电流< $总?CEIL ($电流/ $总量* 100):100; } 否则{ 回声100; }
该脚本执行上传输的字节数目前在总文件大小,再乘以100,并四舍五入到给一个百分比分成一些简单的数学。
有关传输的信息,关键在于有一套与session.upload_progress.prefix指令的值的串联和隐藏session.upload_progress.name字段的值。 因为我的形式通过了“myForm会”,会议的重点是与确定ini_get("session.upload_progress.prefix") . "myForm"ini_get("session.upload_progress.prefix") . "myForm" 。
下面是在行动进度条的截图:
微调行为
PHP提供了一些额外的指令来帮助微调会话上传的行为,你应该知道的。 例如,session.upload_progress.cleanup ,这是默认设置为1,清理后,立即上传已经完成了额外的会话数据。 你必须要小心,以避免潜在的竞争条件。
再看看在代码progress.php ,你会发现,我检查,看看是否$_SESSION[$key]为空或不是,然后再继续。我的JavaScript函数火了每一秒,只要结果从返回progress.php小于100。 如果session.upload_progress.cleanup已启用,我的脚本获取99%的上传和1/2-second后上传完成后,$_SESSION[$key]不会为下一个检查存在的。 如果我不考虑到这一点,然后我的JavaScript函数可能保持射击,上传完成之后也是如此。
다른 두 지시문은 session.upload_progress.freq 및 session.upload_progress.min_freq이며 세션을 업데이트해야 하는 빈도를 결정합니다. 빈도 값은 바이트(예: 100) 또는 총 바이트 수에 대한 백분율(예: 2%)로 제공될 수 있습니다. min_freq 값은 초 단위이며 업데이트 사이의 최소 시간(초)을 나타냅니다. 분명히 min_freq가 1초마다 업데이트되도록 설정된 경우 JavaScript가 100밀리초마다 확인하는 것은 의미가 없습니다.
요약
이제 세션 업로드 진행 기능을 사용하여 파일 업로드 진행 표시줄을 만드는 방법을 확실히 이해하셨을 것입니다. 앞으로는 $_SESSION[$key]["cancel_upload"] 또는 마음속에 떠올릴 수 있는 다른 아이디어를 사용하여 진행 중인 업로드를 취소할 수 있는 옵션을 제공하여 여러 파일을 업로드해 보시기 바랍니다.