问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501
你好,欢迎来到懂视!登录注册
当前位置: 首页 - 正文

php如何实现上传文件显示上传进度百分比

发布网友 发布时间:2022-04-25 22:39

我来回答

3个回答

懂视网 时间:2022-04-28 08:00

php实现上传进度条的方法:首先向服务器端上传一个文件;然后用PHP将此次文件上传的详细信息存储在session当中;接着用Ajax周期性的请求一个服务器端脚本;最后通过浏览器端的Javascript显示更新进度条即可。

推荐:《PHP视频教程》

实现文件上传进度条基本是依靠JS插件或HTML5的File API来完成,其实PHP配合ajax也能实现此功能。

PHP手册对于session上传进度是这么介绍的:

当 session.upload_progress.enabled INI 选项开启时,PHP 能够在每一个文件上传时监测上传进度。 这个信息对上传请求自身并没有什么帮助,但在文件上传时应用可以发送一个POST请求到终端(例如通过XHR)来检查这个状态 

当一个上传在处理中,同时POST一个与INI中设置的session.upload_progress.name同名变量时,上传进度可以在$_SESSION中获得。 当PHP检测到这种POST请求时,它会在$_SESSION中添加一组数据, 索引是 session.upload_progress.prefix 与 session.upload_progress.name连接在一起的值。 通常这些键值可以通过读取INI设置来获得,例如 

<?php
$key = ini_get("session.upload_progress.prefix") . ini_get("session.upload-progress.name");
var_dump($_SESSION[$key]);
?> 

通过将$_SESSION[$key]["cancel_upload"]设置为TRUE,还可以取消一个正在处理中的文件上传。 当在同一个请求中上传多个文件,它仅会取消当前正在处理的文件上传和未处理的文件上传,但是不会移除那些已经完成的上传。 当一个上传请求被这么取消时,$_FILES中的error将会被设置为 UPLOAD_ERR_EXTENSION。 

session.upload_progress.freq 和 session.upload_progress.min_freq INI选项控制了上传进度信息应该多久被重新计算一次。 通过合理设置这两个选项的值,这个功能的开销几乎可以忽略不计。 

注意:为了使这个正常工作,web服务器的请求缓冲区需要禁用,否则 PHP可能仅当文件完全上传完成时才能收到文件上传请求。 已知会缓冲这种大请求的程序有Nginx。

下面原理介绍:
  当浏览器向服务器端上传一个文件时,PHP将会把此次文件上传的详细信息(如上传时间、上传进度等)存储在session当中。然后,随着上传的进行,周期性的更新session中的信息。这样,浏览器端就可以使用Ajax周期性的请求一个服务器端脚本,由该脚本返回session中的进度信息;浏览器端的Javascript即可根据这些信息显示/更新进度条了。

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"

  其中enabled控制upload_progress功能的开启与否,默认开启;
  cleanup 则设置当文件上传的请求提交完成后,是否清除session的相关信息,默认开启,如果需要调试$_SESSION,则应该设为Off。
  prefix 和 name 两项用来设置进度信息在session中存储的变量名/键名。
  freq 和 min_freq 两项用来设置服务器端对进度信息的更新频率。合理的设置这两项可以减轻服务器的负担。
  在上传文件的表单中,需要为该次上传设置一个标识符,并在接下来的过程中使用该标识符来引用进度信息。

  具体的,在上传表单中需要有一个隐藏的input,它的name属性为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]这个变量的结构是这样的:

array (
	'upload_progress_test' => array (
		'start_time' => 1491494993, // 开始时间
		'content_length' => 1410397, // POST请求的总数据长度
		'bytes_processed' => 1410397, // 已收到的数据长度
		'done' => true,  // 请求是否完成 true表示完成,false未完成
		'files' => array (
			0 => array (
				'field_name' => 'file1',
				'name' => 'test.jpg',
				'tmp_name' => 'D:wamp	mpphpE181.tmp',
				'error' => 0,
				'done' => true,
				'start_time' => 1491494993,
				'bytes_processed' => 1410096,
			),
		),
	),
);

这样,我们就可以使用其中的 content_length 和 bytes_processed 两项来得到进度百分比。

原理介绍完了,下面我们来完整的实现一个基于PHP和Javascript的文件上传进度条。

上传表单index.php

<?php session_start(); ?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
 <meta charset="utf-8">
 <title>PHP(5.4) Session 上传进度 Demo</title>
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <meta name="keywords" content=""/>
 <meta name="description" content=""/>
 <meta name="author" content="">
 <link href="https://cdn.bootcss.com/bootstrap/4.0.0-alpha.2/css/bootstrap.min.css" rel="stylesheet">

 <style type="text/css">
 body{
  font-size:1em;
  color:#333;
  font-family: "宋体", Arial, sans-serif;
 }
 h1, h2, h3, h4, h5, h6{
  font-family: "宋体", Georgia, serif;
  color:#000;
  line-height:1.8em;
  margin:0;
 }
 h1{ font-size:1.8em; }
 #wrap{
  margin-top:15px;
  margin-bottom:50px;
  background:#fff;
  border-radius:5px;
  box-shadow:inset 0 0 3px #000,
  0 0 3px #eee;
 }
 #header{
  border-radius:5px 5px 0 0;
  box-shadow:inset 0 0 3px #000;
  padding:0 15px;
  color:#fff;
  background: #333333;
 }
 #header h1{
  color:#fff;
 }

 #article{
  padding:0 15px;
 }
 #footer{
  text-align:center;
  border-top:1px solid #ccc;
  border-radius:0 0 5px 5px;
 }

 .progress {
  width: 100%;
  border: 1px solid #4da8fe;
  border-radius: 40px;
  height: 20px;
  position: relative;
 }

 .progress .labels {
  position: relative;
  text-align: center;

 }

 .progress .bar {
  position: absolute;
  left: 0;
  top: 0;
  background: #4D90FE;
  height: 20px;
  line-height:20px;
  border-radius: 40px;
  min-width: 20px;
 }

 .report-file {
  display: block;
  position: relative;
  width: 120px;
  height: 28px;
  overflow: hidden;
  border: 1px solid #428bca;
  background: none repeat scroll 0 0 #428bca;
  color: #fff;
  cursor: pointer;
  text-align: center;
  float: left;
  margin-right:5px;
 }
 .report-file span {
  cursor: pointer;
  display: block;
  line-height: 28px;
 }
 .file-prew {
  cursor: pointer;
  position: absolute;
  top: 0;
  left:0;
  width: 120px;
  height: 30px;
  font-size: 100px;
  opacity: 0;
  filter: alpha(opacity=0);
 }

 .container{
  padding-left:0;
  padding-right:0;
  margin:0 auto;
 }
 </style>

</head>
<body>

<p id="wrap" class="container">

 <p id="header">
 <h1>Session上传进度 Demo</h1>
 </p>
 <p id="article">

 <form id="upload-form" action="upload.php" method="POST" enctype="multipart/form-data" style="margin:15px 0"
  target="hidden_iframe">
  <input type="hidden" name="<?php echo ini_get("session.upload_progress.name"); ?>" value="test"/>
  <p class="report-file">
  <span>上传文件…</span><input tabindex="3" size="3" name="file1" class="file-prew" type="file" onchange="document.getElementById('textName').value=this.value">
  </p>
  <input type="text" id="textName" style="height: 28px;border:1px solid #f1f1f1" />
  <p>
  <input type="submit" class="btn btn-default" value="上传"/>
  </p>
 </form>

 <p id="progress" class="progress" style="margin-bottom:15px;display:none;">
  <p class="bar" style="width:0%;"></p>
  <p class="labels">0%</p>
 </p>

 </p> <!-- #article -->

 <p id="footer">
 <p> </p>
 </p>
</p><!-- #wrap -->

<iframe id="hidden_iframe" name="hidden_iframe" src="about:blank" style="display:none;"></iframe>

<script src="https://cdn.bootcss.com/jquery/3.1.1/jquery.min.js"></script>
<script type="text/javascript">
 function fetch_progress() {
 $.get('progress.php', {'<?php echo ini_get("session.upload_progress.name"); ?>': 'test'}, function (data) {
  var progress = parseInt(data);

  $('#progress .labels').html(progress + '%');
  $('#progress .bar').css('width', progress + '%');

  if (progress < 100) {
  setTimeout('fetch_progress()', 500);
  } else {
  $('#progress .labels').html('100%');
  }
 }, 'html');
 }

 $('#upload-form').submit(function () {
 $('#progress').show();

 //图片比较小,看不出进度条加载效果,初始设33%
 $('#progress .labels').html('33%');
 $('#progress .bar').css('width', '33%');

 setTimeout('fetch_progress()', 500);
 });
</script>
</body>
</html>

  注意表单中的session.upload_progress.name隐藏项,值设置为了test。表单中仅有一个文件上传input,如果需要,你可以添加多个。
  这里需要特别注意一下表单的target属性,这里设置指向了一个当前页面中的iframe。这一点很关键,通过设置target属性,让表单提交后的页面显示在iframe中,从而避免当前的页面跳转。因为我们还得在当前页面显示进度条呢。

上传文件upload.php

<?php
/**
 * 上传文件
 */
if(is_uploaded_file($_FILES['file1']['tmp_name'])){
	//unlink($_FILES['file1']['tmp_name']);
	$fileName = 'pic_' . date('YmdHis') . mt_rand(10000,99999);
	$ext = substr($_FILES['file1']['name'], strrpos($_FILES['file1']['name'], '.'));

	move_uploaded_file($_FILES['file1']['tmp_name'], $fileName . $ext);
}

ajax获取上传进度progress.php

<?php
/**
 * AJAX获取上传文件进度
 */
session_start();

$i = ini_get('session.upload_progress.name');
//session.upload_progress.name = "PHP_SESSION_UPLOAD_PROGRESS"

$key = ini_get("session.upload_progress.prefix") . $_GET[$i];
//session.upload_progress.prefix = "upload_progress_" . 'test'

if (!empty($_SESSION[$key])) {
	$current = $_SESSION[$key]["bytes_processed"]; // 已收到的数据长度
	$total = $_SESSION[$key]["content_length"]; // POST请求的总数据长度
	echo $current < $total ? ceil($current / $total * 100) : 100;
}else{
	echo 100;
}

注意事项:
1.input标签的位置name为session.upload_progress.name的input标签一定要放在文件input <input type="file" /> 的前面。
2.通过设置 $_SESSION[$key]['cancel_upload'] = true 可取消当次上传。但仅能取消正在上传的文件和尚未开始的文件。已经上传成功的文件不会被删除。
3.应该通过 setTimeout() 来调用 fetch_progress(),这样可以确保一次请求返回之后才开始下一次请求。如果使用 setInterval() 则不能保证这一点,有可能导致进度条出现'不进反退'。

热心网友 时间:2022-04-28 05:08

程序需要php的apc模块的支持,关键点就是在上传的form里添加一个hidden的inpu标签,里面要有name为
APC_UPLOAD_PROGRESS的属性,value值为一个随机数一遍多个人上传。

apc模块的安装方法是,下载php_apc.dll放到ext文件夹下,在php.ini文件里添加
upload_max_filesize =100M
apc.rfc1867 = on
apc.max_file_size = 100M
extension=php_apc.dll
然后测试配置是否成功:
if(apc_fetch)
{echo "apc is working"}
else{echo "apc is not supported!";}

热心网友 时间:2022-04-28 06:26

使用Ajax 方式上传文件,显示进度条一般都要求IE10以上的浏览器,但Chrome Firefox Safari这些版本低些都可以支持;
如果上传文件的话可以使用 jQuery form 插件,如果同时上传多个文件的可以使用 jQuery Uploadify插件,用SWFUpload没有浏览器的*但是要求浏览安装Flash插件,当前还有很多这方面的插件,你可以根据自己使用的习惯来选择;
声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。
E-MAIL:11247931@qq.com
围裙面料有哪些材质 围裙款式种类关于围裙款式种类 辉瑞、莫德纳和强生计划推出 RSV 疫苗,年内或将向监管机构 Pfizer/BioNTech新冠mRNA疫苗选择了BNT162b2启动临床2/3期 辉瑞新冠疫苗什么技术 美国辉瑞预防什么 免责条款的意思是什么? 微电子专业的女生就业前景如何? 土建工程清包五项是什么 在工地承包五项、具体的都应该干些什么 文件上传时,进度条的设计原理是什么? ocia有机认证标准的具体内容 如何实现上传文件带进度条 有机食品的认证标准是什么? 上传文件时怎么显示上传的进度 什么是有机认证? 有机认证是什么? 中国电信企业云盘查看上传文件进度的指引是怎样的? 欧盟有机认证是什么意思? 如何获取FileUpload上传文件的进度 独立显卡只有三种分辫率怎么办? 有机认证的概述 一个女孩问我喜欢他什么我该怎么回答?? 显卡只有一个风扇转动怎么回事? 什么是欧盟有机认证? 当一个女人问你喜欢她什么 怎么回答? 显卡只有一个hdmi接口怎么双屏 显卡只有一个插口 有信号 有机食品认证的简介 女生问你喜欢她什么怎么回答最好 农产品的有机认证 世界上有哪些有机认证的单位? PHP中使用Session配合Javascript实现文件上传进度条功能 有机认证的标准有区别吗? 阿里云OSS服务,怎么做上传进度?包括大文件和小文件。 前端上传文件实时显示进度条和上传速度的工作原理是怎样的 百度网盘上传进度往回走怎么办?还卡进度? php,使用session上传文件进度问题 java实现文件上传及进度条的几种做法 详细?? java中的文件上传进度条原理是什么哈 游戏名字,有&quot;微&quot;字的。要好听一点的.格式:贵族:XXX 三个字 鱼露和酱油吃起来区别 为什么鱼露也叫鱼酱油? 鱼露和味极鲜和生抽调酱油要加什么 调复合小酱油用什么牌子的鱼露好 生抽、老抽、酱油、虾油、鱼露 谁给我解释一下这些 酱油鱼露等问题 单反摄像机的代表产品 虾油就是鱼露吗? 单反摄像机有哪些
  • 焦点

最新推荐

猜你喜欢

热门推荐