文件上传:百分比完成进度条

15
我正在尝试在BuddyPress中的头像上传中添加“已完成百分比”进度条。目的是在上传完成之前防止用户离开页面。
BuddyPress中的上传过程由bp-core / bp-core-avatars.php文件中的bp_core_avatar_handle_upload()处理。该函数首先使用bp_core_check_avatar_upload()检查文件是否已经正确上传,然后检查文件大小是否符合限制,并且有可接受的文件扩展名(jpg,gif,png)。如果一切都正确,允许用户裁剪图像(使用Jcrop),然后将图像移动到其真实位置。
实际上传由WordPress函数wp_handle_upload处理。
如何创建“已完成百分比”进度条并在文件上传时显示它呢?
5个回答

13

我不熟悉BuddyPress,但所有的上传处理器(包括androbin提到的HTML5 XHR)都有一个文件进度挂载点,您可以将其绑定。

我曾经使用过uploadifyuploadifiveswfupload,它们都可以与同一个进度函数处理器交互,以实现相同的进度条结果。

// SWFUpload
$elem.bind('uploadProgress', function(event, file, bytesLoaded) { fnProgress(file, bytesLoaded); })

// Uploadify
$elem.uploadify({ onUploadProgress: function (file, bytesUploaded, bytesTotal, totalBytesUploaded, totalBytesTotal) { fnProgress(file, bytesUploaded); });

// Uploadfive
$elem.uploadifive({ onProgress: function(file, e) { fn.onProgress(file, e.loaded); });

Uploadifive是基于HTML5的上传器,它简单地绑定到XHR“进度”事件,所以所有这些属性对于任何HTML5上传器都可用。

至于实际的进度条代码...

HTML:

<div class='progressWrapper' style='float: left; width: 100%'>
    <div class='progress' style='float: left; width: 0%; color: red'></div>
    <div class='progressText' style='float: left;></div>
</div>

JS:

var fnProgress = function(file, bytes) {
    var percentage = (bytesLoaded / file.size) * 100;

    // Update DOM
    $('.progress').css({ 'width': percentage + '%' });
    $('.progressText').html(Math.round(percentage + "%");
}

7
你应该使用XHR对象。我不知道这是否对你有所帮助,但我有一个简单的XHR上传器可供使用。
HTML:
    <form id="uploader" enctype="multipart/form-data" action="uploadimage.php" method="post">
        <input type="file" id="file" name="file[]" multiple="multiple" accept="image/jpeg" /><br/>
        <input type="submit" value="Upload" />
        <div class="list" style="background-color:#000;color:#FFF;padding:5px;display:none;border-radius:5px;">
        </div>
    </form>

JS:

$("#uploader").submit(function(){
    $('#uploader .list').fadeIn(100).css("width","0px");
    var data = new FormData();
    // if you want to append any other data: data.append("ID","");
    $.each($('#file')[0].files, function(i, file) {
        data.append('file-'+i, file);
    });
    $.ajax({
        url: 'uploadimage.php',
        data: data,
        cache: false,
        contentType: false,
        processData: false,
        type: 'POST',
        xhr: function() {  // custom xhr
            myXhr = $.ajaxSettings.xhr();
            if(myXhr.upload){ // check if upload property exists
                myXhr.upload.addEventListener('progress',progressHandlingFunction, false); // for handling the progress of the upload
            }
            return myXhr;
        },
        success: function(data2){
            $('#uploader .list').css({
                "width":"200px",
                "text-align":"center",
                "margin":"10px 0 10px 0"
            }).html("DONE!").delay(2000).fadeOut(500);
            if (data2 == "ERROR_FILESIZE"){
                return alert("Choose another file");
            }
                            else{ /*change location*/ }
        });
    return false;
});

在这种情况下,我使用uploadimage.php上传文件,如果它打印出"ERROR_FILESIZE",那么它就会弹出错误提示。

3
我认为在你担心客户端问题之前,你应该了解服务器端的要求,以实际完成此操作。对于PHP而言,除非wp_handle_upload()使用其他方法,否则需要启用session.upload_progress,所以我只是猜测,但很有可能他们确实使用常规的PHP会话,因此需要启用它。如果您查看给定链接的评论,许多用户都说进度状态在某些环境下无法正常工作,例如大多数时间里在共享托管环境中使用的PHP on FastCGI。
现在,这里有很多人告诉你使用XHR上传器,但问题在于他们给出了一个自定义upload.php脚本的示例或类似于此的东西来发送数据,但你正在使用一个你无法控制(有点)的WordPress插件。
因此,考虑到wp_handle_upload()实际上并不以AJAX方式工作,那么当文件上传表单提交按钮被点击时,您将不得不钩住一个事件并在JS中设置一个定时器,该定时器调用一些URL,其中传递表单数据(如ID),然后查询带有该ID的会话以检查文件的进度:
 $_SESSION["upload_id"]["content_length"]
 $_SESSION["upload_id"]["bytes_processed"]

有了这些数据,您可以计算出已传输的数据量。您可以设置JS定时器每秒调用一次,但如果上传的文件不是很大(比如大于1MB),并且他们的连接很好,那么就不会有太多进度需要通知。

请点击此链接,了解如何处理这个会话上传数据的逐步示例。


1
你可以查看这个URL来获取XHR示例。
访问https://codepen.io/PerfectIsShit/pen/zogMXP
<h2>HTML5 File Upload Progress Bar Tutorial</h2>
<form id="upload_form" enctype="multipart/form-data" method="post">
  <input type="file" name="file1" id="file1" onchange="uploadFile()"><br>
  <progress id="progressBar" value="0" max="100" style="width:300px;"></progress>
  <h3 id="status"></h3>
  <p id="loaded_n_total"></p>
</form>

function _(el) {
  return document.getElementById(el);
}

function uploadFile() {
  var file = _("file1").files[0];
  // alert(file.name+" | "+file.size+" | "+file.type);
  var formdata = new FormData();
  formdata.append("file1", file);
  var ajax = new XMLHttpRequest();
  ajax.upload.addEventListener("progress", progressHandler, false);
  ajax.addEventListener("load", completeHandler, false);
  ajax.addEventListener("error", errorHandler, false);
  ajax.addEventListener("abort", abortHandler, false);
  ajax.open("POST", "file_upload_parser.php"); // http://www.developphp.com/video/JavaScript/File-Upload-Progress-Bar-Meter-Tutorial-Ajax-PHP
  //use file_upload_parser.php from above url
  ajax.send(formdata);
}

function progressHandler(event) {
  _("loaded_n_total").innerHTML = "Uploaded " + event.loaded + " bytes of " + event.total;
  var percent = (event.loaded / event.total) * 100;
  _("progressBar").value = Math.round(percent);
  _("status").innerHTML = Math.round(percent) + "% uploaded... please wait";
}

function completeHandler(event) {
  _("status").innerHTML = event.target.responseText;
  _("progressBar").value = 0; //wil clear progress bar after successful upload
}

function errorHandler(event) {
  _("status").innerHTML = "Upload Failed";
}

function abortHandler(event) {
  _("status").innerHTML = "Upload Aborted";
}

0

你需要注入进度条。

我认为唯一的方法是使用过滤器钩子apply_filters('bp_core_pre_avatar_handle_upload'等)覆盖函数bp_core_avatar_handle_upload。

你最终会复制大部分函数,但应该能够添加你的进度条代码。

如果你成功了,应该将其提交为增强票据;这是一个好主意。


嗨,shanebp - 我正在考虑做类似的事情。然而,我遇到了生成进度条的代码问题。我已经编辑了我的问题。有什么想法吗?我很苦恼 :( - henrywright
1
没关系!我其实也没有尝试过,一直在试着自己做。但现在看到有可用的脚本了!你有什么推荐吗?http://www.johnboy.com/php-upload-progress-bar/ 看起来很简单。 - henrywright
我注意到大多数PHP解决方案需要在服务器上安装APC - 这是我无法保证在每个安装此解决方案的站点上都有的东西。 - henrywright
这已经不再是问题了,请参见http://www.php.net/manual/en/session.upload-progress.php(尽管这要求PHP _不_通过FastCGI运行 - 但你不能一直取悦所有人。) - CBroe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接