PHP中的上传进度条

83

有谁知道如何在php中获取上传进度条?我正在编写照片相册上传器的代码,希望在照片上传时显示进度条。

我对php还比较陌生,不了解所有相关内容。


https://dev59.com/Imkv5IYBdhLWcg3wnCA7#10477249 - Alfred
10个回答

70

经过数小时的谷歌搜索和尝试脚本后,这是目前我找到最简单、最好用的上传工具。

https://github.com/FineUploader/fine-uploader

它不需要APC或其他外部PHP库,在共享主机上也可以获得文件上传进度反馈,并声称支持HTML5拖放(个人未经测试)和多文件上传。


11
我认为你应该使用这个链接:https://github.com/valums/file-uploader - 这是同一个作者所写的。 - Michael Reed
6
请查看 Session Upload Progress,这是 PHP 提供的开箱即用的文件上传进度获取功能。 - hakre
7
@jpeskin对开发者有点不公平。仅仅因为您“提出支付报酬”并不意味着他们像妓女一样义务为您工作。如果您无法解决调试问题,那么请不要指责任何人--您在互联网上找到的软件是"原样"提供的,所以请不要抨击那些仅仅在尝试帮助您的人。 - sucitivel
4
更详细一些:我提出支付报酬,他接受了,然后我们费力地记录下我们发现的所有漏洞,之后他停止回复任何邮件(只是礼貌地请求更新状态和是否还有兴趣完成工作的邮件)。我不认为有人必须为钱工作。这只是给其他可能想知道开发者可用性和/或自由职业工作兴趣的人一个观察数据点。项目已被复制,所以我不是唯一感到开发者对维护失去兴趣的人。 - jpeskin
5
这个链接指的是http://blueimp.github.com/jQuery-File-Upload/。它非常好用,至少我很喜欢,因为在Ubuntu下没有任何卡顿 =) - BeRocket
显示剩余3条评论

13
如果你已经安装了 APC,它会具有用于上传进度的回调钩子。
Rasmus Lerdorf(PHP 的创造者)在此使用 YUI 进行了示例演示 (还有这里的PHP源码)。
请参见此处的文档

不管是相同的链接还是PHP源代码的链接都不能用了,你有备用链接吗? - supersan
@supersan 这个回答已经非常过时了。APC 已经死了,而 Session Upload API 现在是一个单独的东西。如果服务器使用 FastCGI,它也不起作用...这些天大多数服务器都出于安全原因使用 FastCGI。 - Powerlord

13

很抱歉,据我所知,由于PHP的工作原理,纯PHP上传进度条甚至PHP/Javascript上传进度条都不可能实现。你最好使用某种形式的Flash上传工具。

这是因为你的脚本在超全局变量(包括$_FILES)被填充之前不会被执行。当你的PHP脚本被调用时,文件已经完全上传。

编辑:这已经不再是真的了。这是在2010年时的情况。


13
为什么会有三个踩?这是真的,而且完全不应该被踩。我敢挑战任何人向我展示一个在本地 PHP 上运行且不需要额外扩展/ Apache 模块/ Perl 脚本/ 其他东西即可工作的进度条。 - Pekka
1
好的,现在是2011年,由于HTML5的出现,这已经成为可能。请参见此处的第一个回答:https://dev59.com/zXVD5IYBdhLWcg3wI36L - Zarel
10
现在是2012年,HTML5中通过XMLHttpRequest进行文件上传在所有主流浏览器中仍然不可用。 - Damien B
3
不正确。如果你安装了APC(你应该安装),你可以完全使用PHP本地化完成它,而且不需要使用Javascript。 - Ariel
2
@Pekka웃 更不用说在PHP >=5.4中使用会话信息上传了。 - Wookie88

8

以下是一种适用于 PHP(5.2+)且不需要 Flash 的方法,我觉得非常好用:

首先,请参考这篇文章,了解如何启用“uploadprogress”扩展。

然后,在包含上传文件表单的页面中,创建以下的 iframe:

<iframe id="progress_iframe" src="" style="display:none;" scrolling="no" frameborder="0"></iframe>

接下来,请将以下代码添加到您的“提交”按钮中:

然后,将此代码添加到您的“提交”按钮中:

onclick="function set() { f=document.getElementById('progress_iframe'); f.style.display='block'; f.src='uploadprogress.php?id=<?=$upload_id?>';} setTimeout(set);"

现在您的表单中有一个隐藏的 iframe,当您点击“提交”开始上传文件时,它将变得可见并显示 uploadprogress.php 的内容。$upload_id 必须与您在表单中使用作为隐藏字段“UPLOAD_IDENTIFIER”值的相同值相匹配。 uploadprogress.php 本身看起来大致如下(请根据您的需要进行修复和调整):
<html>
<head>
<META HTTP-EQUIV='REFRESH' CONTENT='1;URL=?id=<?=$_GET['id']?>'>
</head>
<body>
Upload progress:<br />
<?php
    if(!$_GET['id']) die;
    $info = uploadprogress_get_info($_GET['id']);
    $kbytes_total = round($info['bytes_total'] / 1024);
    $kbytes_uploaded = round($info['bytes_uploaded'] / 1024);
    echo $kbytes_uploaded.'/'.$kbytes_total.' KB';
?>
</body>
</html>

请注意,此处每秒钟会自动刷新一次。如果您喜欢,可以在此处添加一些漂亮的可视化进度条(例如两个不同颜色的嵌套
)。上传进度的iframe自然只在上传过程中起作用,并在表单提交并浏览器重新加载到下一页后结束其可见生命周期。

在PHP中,如何在没有$_FILES的情况下上传文件? - user1432124

3

实现上传进度条很容易,不需要任何额外的PHP扩展、JavaScript或Flash。但是需要PHP 5.4及更高版本

您需要通过在php.ini中将指令session.upload_progress.enabled设置为On来启用收集上传进度信息。

然后,在任何其他文件输入之前,只需向HTML上传表单添加一个隐藏输入即可。该隐藏输入的HTML属性name应与php.ini中的指令session.upload_progress.name的值相同(最好加上session.upload_progress.prefix)。value属性由您决定,它将用作会话键的一部分。

HTML表单可能如下所示:

<form action="upload.php" method="POST" enctype="multipart/form-data">
   <input type="hidden" name="<?php echo ini_get('session.upload_progress.prefix').ini_get('session.upload_progress.name'); ?>" value="myupload" />
   <input type="file" name="file1" />
   <input type="submit" />
</form>

当您发送此表单时,PHP应在$_SESSION超全局结构中创建一个新的键,该键将填充上传状态信息。该键是隐藏输入的名称和值连接而成。
在PHP中,您可以查看已填充的上传信息:
var_dump($_SESSION[
    ini_get('session.upload_progress.prefix')
   .ini_get('session.upload_progress.name')
   .'_myupload'
]);

输出结果将类似于以下内容:
$_SESSION["upload_progress_myupload"] = array(
  "start_time" => 1234567890,   // The request time
  "content_length" => 57343257, // POST content length
  "bytes_processed" => 54321,   // Amount of bytes received and processed
  "done" => false,              // true when the POST handler has finished, successfully or not
  "files" => array(
    0 => array(
      "field_name" => "file1",    // Name of the <input /> field
      // The following 3 elements equals those in $_FILES
      "name" => "filename.ext",
      "tmp_name" => "/tmp/phpxxxxxx",
      "error" => 0,
      "done" => false,            // True when the POST handler has finished handling this file
      "start_time" => 1234567890, // When this file has started to be processed
      "bytes_processed" => 54321, // Number of bytes received and processed for this file
    )
  )
);

这里提供了创建进度条所需的所有信息 - 您可以获得上传是否仍在进行中的信息,要传输的总字节数以及已传输的字节数。
为了向用户展示上传进度,请编写另一个PHP脚本,该脚本仅查看会话中的上传信息并以JSON格式返回它。例如,可以使用AJAX每秒钟调用一次此脚本,并将信息呈现给用户。
您甚至可以通过将$_SESSION[$key]['cancel_upload']设置为true来取消上传。
有关详细信息、其他设置和用户评论,请参见PHP手册

2
另一个完整的JS上传程序:http://developers.sirika.com/mfu/
  • 免费(BSD许可证)
  • 国际化
  • 跨浏览器兼容
  • 您可以选择安装APC或不安装(不确定进度条VS确定进度条)
  • 可自定义外观,因为它使用dojo模板机制。您可以根据自己的CSS在模板中添加类/ ID

玩得开心!


2
齿轮和HTML5在通过AJAX上传文件时,HttpRequest对象中有一个进度事件。

http://developer.mozilla.org/en/Using_files_from_web_applications

您的其他选择,就像其他人已经回答的一样,包括:
  1. 基于Flash的上传器。
  2. 基于Java的上传器。
  3. 向Web服务器发送第二个comet-style请求或脚本来报告接收到的数据大小。一些Web服务器(如Lighttpd)提供了模块来在进程中执行此操作,以节省调用外部脚本或进程的开销。

从技术上讲,还有第四种选择,类似于YouTube上传,在使用Gears或HTML5时,可以使用Blob将文件分成小块,并逐个上传每个块。完成每个块后,您可以更新进度状态。


2

HTML5引入了一个文件上传API,允许您监控文件上传的进度,但对于旧版浏览器,有plupload框架专门用于监控文件上传并提供相关信息。此外,它还具有大量回调函数,因此可以在所有浏览器上运行。


1

您需要使用JavaScript来创建进度条。一个简单的谷歌搜索让我找到了这篇文章:WebAppers Simple Javascript Progress Bar with CSS

Dojo File Upload Progress Bar Widget是另一种使用Dojo JavaScript框架的选择。

编辑:假设您正在上传大量图像(例如照片相册),并将它们POST到您的PHP脚本中,您可以使用JavaScript从POST中读取结果,并根据已上传的图像数量/总图像数量更新进度条。这会导致每个POST完成后才更新。请查看此处以获取有关如何使用JS进行POST的一些信息。


6
据我所见,JavaScript进度条很好,但与文件上传无关。而Dojo上传进度条没有提供任何与PHP交互的接口。如果我错了,请纠正我。 - Pekka

1

可以使用php/ajax进度条(请查看pear中的Html_Ajax库)来实现。但是这需要将一个自定义模块安装到php中。

其他方法需要使用iframe,通过它php可以查看文件上传了多少。然而,一些浏览器插件可能会阻止这个隐藏的iframe,因为隐藏的iframes经常用于向用户计算机发送恶意数据。

如果您无法控制服务器,则最好使用某种形式的flash进度条。


有些插件可能会阻止 iframe,但浏览器呢?你能举个例子吗? - ya23
搜索“ajax php文件上传”这些词会返回前5个结果中的4个都使用了iframe(不确定第5个是否使用,因为页面无法加载)。请查看每个网站上的示例。 - Ali Lown
确实,他们使用iframes,但并未提到它可以在任何情况下被阻止。或者我错过了这一点? - ya23
抱歉,我误解了你的问题,不,我不能给出任何直接阻止iframe的浏览器示例,我想到的是人们与它们一起使用的插件,例如可以阻止iframes的noscript。为了以后的参考,我已更新了帖子中的文本。 - Ali Lown

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