上传进度 - 有时$ _SESSION [$ key]为空 [英] Upload Progress - Sometimes $_SESSION[$key] is Empty

查看:154
本文介绍了上传进度 - 有时$ _SESSION [$ key]为空的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有Ubuntu 12.04 LTS和PHP5.5与Apache2通过PHP会话上传进度实现上传进度。



问题在于它有时候有效,有时不起作用。我的意思是,有时我会在上传开始时直接获得进度百分比,而没有完成上传(这意味着在这种情况下$ _SESSION [$ key]是空的,但是为什么?)



我尝试将session.upload_progress.cleanup的值设置为On和Off,但它没有改变任何内容。



你可以试试你自己在这个URL:
http://138.128.124.172/upload_progress

php.ini 中,我有以下与上传相关的设置:

 ; ;;;;;;;;;;;;;;; 
;文件上传;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;是否允许HTTP文件上传
; http://php.net/file-uploads
file_uploads =在

; HTTP上传文件的临时目录(如果不是
,则使用系统默认值)。
; http://php.net/upload-tmp-dir
; upload_tmp_dir =

;上传文件的最大允许大小。
; http://php.net/upload-max-filesize
upload_max_filesize = 100M

;可通过单个请求上传的最大文件数量
max_file_uploads = 20


;在$ _SESSION
中启用上传进度追踪;默认值:在
;发展价值:关于
;生产价值:在
; http://php.net/session.upload-progress.enabled
session.upload_progress.enabled =在

;所有POST数据被读取后立即清除进度信息
; (即上传完成)。
;默认值:在
;发展价值:关于
;生产价值:在
; http://php.net/session.upload-progress.cleanup
session.upload_progress.cleanup =关

;在$ _SESSION
中用于上传进度键的前缀;默认值:upload_progress_
;开发价值:upload_progress_
;生产值:upload_progress_
; http://php.net/session.upload-progress.prefix


; session.upload_progress.prefix =upload_progress_

;索引名称(与前缀连接)在$ _SESSION
;包含上传进度信息
;默认值:PHP_SESSION_UPLOAD_PROGRESS
;开发价值:PHP_SESSION_UPLOAD_PROGRESS
;生产值:PHP_SESSION_UPLOAD_PROGRESS
; http://php.net/session.upload-progress.name
; session.upload_progress.name =PHP_SESSION_UPLOAD_PROGRESS

;上传进度应该多久更新一次。
;以百分比(每个文件)或以字节
给出;默认值:1%
;发展价值:1%
;产值:1%
; http://php.net/session.upload-progress.freq
; session.upload_progress.freq =1%


;更新之间的最小延迟,以秒为单位
;默认值:1
;发展价值:1
;产值:1
; http://php.net/session.upload-progress.min-freq
; session.upload_progress.min_freq =1

在PHP方面:我在页面中有下面的代码: progress.php

 在session_start(); 
$ key = ini_get(session.upload_progress.prefix)。 myForm会;
if(!empty($ _ SESSION [$ key])){
$ current = $ _SESSION [$ key] [bytes_processed];
$ total = $ _SESSION [$ key] [content_length];
echo $ current< $总? ceil($ current / $ total * 100):100;
}
else {
echo 100;



$ b

在客户端,我在页面中有下面的代码 index.php

 <?php 

if($ _SERVER [REQUEST_METHOD ($ _ FILES [userfile])){
// move_uploaded_file()
}
?>

< style>
#bar_blank {
border:solid 1px#000;
height:20px;
width:300px;
}

#bar_color {
background-color:#006666;
height:20px;
width:0px;
}

#bar_blank,#hidden_​​iframe {
display:none;
}
< / style>


< html>
< head>
< title>档案上载进度栏< / title>
< / head>
< body>
< div id =bar_blank>
< div id =bar_color>< / div>
< / div>
< div id =status>< / div>
< form action =<?php echo $ _SERVER [PHP_SELF];?> method =POSTid =myFormenctype =multipart / form-datatarget =hidden_​​iframe>
< input type =hiddenvalue =myFormname =<?php echo ini_get(session.upload_progress.name);?>>
< input type =submitvalue =开始上传>
< / form>


< iframe id =hidden_​​iframename =hidden_​​iframesrc =about:blank>< / iframe>
< / body>
< / html>


< script>

函数toggleBarVisibility(){
var e = document.getElementById(bar_blank);
e.style.display =(e.style.display ==block)? none:block;
}

函数createRequestObject(){
var http;
if(navigator.appName ==Microsoft Internet Explorer){
http = new ActiveXObject(Microsoft.XMLHTTP);
}
else {
http = new XMLHttpRequest();
}
return http;


函数sendRequest(){
var http = createRequestObject();
http.open(GET,progress.php);
http.onreadystatechange = function(){handleResponse(http)};
http.send(null);
}

函数handleResponse(http){
var response;
if(http.readyState == 4){
response = http.responseText; //警报(响应);返回;
document.getElementById(bar_color)。style.width = response +%;
document.getElementById(status)。innerHTML = response +%;

if(response< 100){
setTimeout(sendRequest(),1000);
}
else {
toggleBarVisibility();
document.getElementById(status)。innerHTML =完成。

document.getElementById(bar_color)。style.width = 0 +%;




$ b函数startUpload(){
toggleBarVisibility();
setTimeout(sendRequest(),1000);


(function(){
document.getElementById(myForm)。onsubmit = startUpload;
})();

< / script>

我对HTML5,Jquery或flash不感兴趣。我会很感激,如果你也暗示我更好的方法来获得一个强大的方式来实现上传与进度条。



感谢您的帮助! 'd建议两件事:


  1. 制作隐藏字段动态值

$ _ SESSION ['ukey'] = substr(md5(uniqid(rand(),true)),0,6);



< input type =hiddenvalue =<?php echo $ _SESSION ['ukey']?> name =<?php echo ini_get(session.upload_progress.name);?>>



实现你可以再次发送相同的文件名,它会工作,你会得到唯一的会话ID。你也可以在 php.ini 值中使用 session.upload_progress.cleanup = Off ,所以会话中的数据将在那里达到100%后。在progres.php中更改为 $ key = ini_get(session.upload_progress.prefix)。 echo $ _SESSION ['ukey'];


  1. 导致麻烦的代码:


    else {
    echo 100;



    $ b

    原因是在某些中间设备或apache或者transit中可能会有缓冲,所以<$ c即使浏览器已经发送了所有100%的POST数据,$ c> $ _ SESSION [$ key] 也将被初始化。这是我在某些ISP的情况。我删除了这个代码,它工作正常。通过这个,你实现了AJAX将数据总是不停留在这个。你只需要处理异常,因为TCP会因为某种原因而下降,而AJAX会在你关闭浏览器之前无休止地尝试池化。但是我不知道这会发生多少次/如果发生的话。


    I have Ubuntu 12.04 LTS and using PHP 5.5 with Apache2 to implement the upload progress via the PHP session upload progress.

    The issue is that it works sometimes and sometimes it doesn't work. I mean sometimes I get the progress percentage 100% direct at the beginning of the upload without finishing the upload (which means the $_SESSION[$key] is empty in that cases, but why?!)

    I tried turning the value of session.upload_progress.cleanup to On and Off, but it didn't change anything.

    You can try it yourself on this URL:
    http://138.128.124.172/upload_progress

    In the php.ini, I have the below settings related to the upload:

    ;;;;;;;;;;;;;;;;
    ; File Uploads ;
    ;;;;;;;;;;;;;;;;
    
    ; Whether to allow HTTP file uploads.
    ; http://php.net/file-uploads
    file_uploads = On
    
    ; Temporary directory for HTTP uploaded files (will use system default if not
    ; specified).
    ; http://php.net/upload-tmp-dir
    ;upload_tmp_dir =
    
    ; Maximum allowed size for uploaded files.
    ; http://php.net/upload-max-filesize
    upload_max_filesize = 100M
    
    ; Maximum number of files that can be uploaded via a single request
    max_file_uploads = 20
    
    
    ; Enable upload progress tracking in $_SESSION
    ; Default Value: On
    ; Development Value: On
    ; Production Value: On
    ; http://php.net/session.upload-progress.enabled
    session.upload_progress.enabled = On
    
    ; Cleanup the progress information as soon as all POST data has been read
    ; (i.e. upload completed).
    ; Default Value: On
    ; Development Value: On
    ; Production Value: On
    ; http://php.net/session.upload-progress.cleanup
    session.upload_progress.cleanup = Off
    
    ; A prefix used for the upload progress key in $_SESSION
    ; Default Value: "upload_progress_"
    ; Development Value: "upload_progress_"
    ; Production Value: "upload_progress_"
    ; http://php.net/session.upload-progress.prefix
    
    
    ;session.upload_progress.prefix = "upload_progress_"
    
    ; The index name (concatenated with the prefix) in $_SESSION
    ; containing the upload progress information
    ; Default Value: "PHP_SESSION_UPLOAD_PROGRESS"
    ; Development Value: "PHP_SESSION_UPLOAD_PROGRESS"
    ; Production Value: "PHP_SESSION_UPLOAD_PROGRESS"
    ; http://php.net/session.upload-progress.name
    ;session.upload_progress.name = "PHP_SESSION_UPLOAD_PROGRESS"
    
    ; How frequently the upload progress should be updated.
    ; Given either in percentages (per-file), or in bytes
    ; Default Value: "1%"
    ; Development Value: "1%"
    ; Production Value: "1%"
    ; http://php.net/session.upload-progress.freq
    ;session.upload_progress.freq =  "1%"
    
    
    ; The minimum delay between updates, in seconds
    ; Default Value: 1
    ; Development Value: 1
    ; Production Value: 1
    ; http://php.net/session.upload-progress.min-freq
    ;session.upload_progress.min_freq = "1"
    

    At the PHP side: I have the below code inside the page: progress.php:

    session_start();
    $key = ini_get("session.upload_progress.prefix") . "myForm";
    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;
    }
    

    At the client side, I have the below code in the page index.php

    <?php
    
    if ($_SERVER["REQUEST_METHOD"] == "POST" && !empty($_FILES["userfile"])) {
        // move_uploaded_file()
    }
    ?>
    
    <style>
        #bar_blank {
            border: solid 1px #000;
            height: 20px;
            width: 300px;
        }
    
        #bar_color {
            background-color: #006666;
            height: 20px;
            width: 0px;
        }
    
        #bar_blank, #hidden_iframe {
            display: none;
        }
    </style>
    
    
    <html>
        <head>
            <title>File Upload Progress Bar</title>
        </head>
        <body>
            <div id="bar_blank">
                <div id="bar_color"></div>
            </div>
            <div id="status"></div>
            <form action="<?php echo $_SERVER["PHP_SELF"]; ?>" method="POST" id="myForm" enctype="multipart/form-data" target="hidden_iframe">
                <input type="hidden" value="myForm" name="<?php echo ini_get("session.upload_progress.name"); ?>">
                <input type="file" name="userfile"><br>
                <input type="submit" value="Start Upload">
            </form>
    
    
            <iframe id="hidden_iframe" name="hidden_iframe" src="about:blank"></iframe>
        </body>
    </html>
    
    
    <script>
    
    function toggleBarVisibility() {
        var e = document.getElementById("bar_blank");
        e.style.display = (e.style.display == "block") ? "none" : "block";
    }
    
    function createRequestObject() {
        var http;
        if (navigator.appName == "Microsoft Internet Explorer") {
            http = new ActiveXObject("Microsoft.XMLHTTP");
        }
        else {
            http = new XMLHttpRequest();
        }
        return http;
    }
    
    function sendRequest() {
        var http = createRequestObject();
        http.open("GET", "progress.php");
        http.onreadystatechange = function () { handleResponse(http) };
        http.send(null);
    }
    
    function handleResponse(http) {
        var response;
        if (http.readyState == 4) {
            response = http.responseText;  //alert(response);return;
            document.getElementById("bar_color").style.width = response + "%";
            document.getElementById("status").innerHTML = response + "%";
    
            if (response < 100) {
                setTimeout("sendRequest()", 1000);
            }
            else {
                toggleBarVisibility();
                document.getElementById("status").innerHTML = "Done.";
    
                document.getElementById("bar_color").style.width = 0 + "%";
    
            }
        }
    }
    
    function startUpload() {
        toggleBarVisibility();
        setTimeout("sendRequest()", 1000);
    }
    
    (function () {
        document.getElementById("myForm").onsubmit = startUpload;
    })();
    
    </script>
    

    I am not interested in the HTML5, Jquery or the flash. I would be thankful if you hint me also about better approaches to get a robust way to implement the upload with a progress bar.

    Thanks for your help!

    解决方案

    Older post, but I'd suggest two things:

    1. Make hidden field dynamic value

    $_SESSION['ukey'] = substr(md5(uniqid(rand(), true)),0,6);

    <input type="hidden" value="<?php echo $_SESSION['ukey'] ?>" name="<?php echo ini_get("session.upload_progress.name"); ?>">

    By this you achieve that you can send same filenames again and it will work, you will get unique session id. Also you can use in php.ini the value session.upload_progress.cleanup = Off so data in session will be there after 100% is reached. In progres.php change to $key = ini_get("session.upload_progress.prefix") . echo $_SESSION['ukey'];

    1. In progress script also this part of the code causing trouble:

    else { echo 100; }

    The reason is that there might be buffering in some intermediate device or apache or in the transit, so $_SESSION[$key] will be initialised even after browser already send all 100% of POST data. This is my scenario at certain ISPs. I removed this code and it is working fine. By this you achieve that AJAX will be pooling data always and not hang on this. You only need to handle exception when TCP would for some reason dropped and AJAX would be trying pooling endlessly until you close browser. But I don't know how often this would happen / if it happens.

    这篇关于上传进度 - 有时$ _SESSION [$ key]为空的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆