SWFUpload是一个客户端文件上传工具,最初由Vinterwebb.se开发,它通过整合Flash与JavaScript技术为WEB开发者提供了一个具有丰富功能继而超越传统<input type="file" />标签的文件上传模式。
其官方网站:http://swfupload.org/
SWFUpload的主要特点
* 可以同时上传多个文件;
* 类似AJAX的无刷新上传;
* 可以显示上传进度;
* 良好的浏览器兼容性;
* 兼容其他JavaScript库 (例如:jQuery, Prototype等);
* 支持Flash 8和Flash 9;
SWFUpload不同于其他基于Flash构建的上传工具,它有着优雅的代码设计,开发者可以利用XHTML、CSS和JavaScript来随心所欲的定制它在浏览器下的外观;它还提供了一组简明的JavaScript事件,借助它们开发者可以方便的在文件上传过程中更新页面内容来营造各种动态效果。
我们来看看基本的实例:
一、前端文件:upload_batch.tpl(模板引擎:smarty)
<link type="text/css" href="swfupload/default.css" rel="stylesheet" />
<script type="text/javascript" src="swfupload/swfupload.js"></script>
<script type="text/javascript" src="swfupload/swfupload.queue.js"></script>
<script type="text/javascript" src="swfupload/fileprogress.js"></script>
<script type="text/javascript" src="swfupload/handlers.js"></script>
<script type="text/javascript">
window.onbeforeunload = function() //离开时弹出提醒对话框 当上传成功后自动跳转时,不进行提示,由自定义变量level值控制
{
var level = document.getElementById("level").value;
if(level == 1) {
return '';
}
}
</script>
<div id="content01" style="position:relative;">
<form id="form1" name="form1" action="index.php" method="post" enctype="multipart/form-data" >
<span class="right" id="choose_album" style="display:;">
请选择所属相册:
<select name="picgid" id="picgid" class="border var_h6" οnchange="setPost();">
{section name=loop loop=$albumrs}
<option value="{$albumrs[loop].id}" {if $albumrs[loop].id == $aid}selected{/if}>{$albumrs[loop].name}</option>
{/section}
</select> 或者<a οnclick="javascript:c_al_js()" style="cursor:pointer;">创建新相册</a></span>
<div id="overlay"style="position:absolute; top:0; left:0; background:#fff; width:120px; height:35px; display:none;"></div>
<span id="spanButtonPlaceHolder"></span>
<div class="flash clearfix">
<div class="up_detail">请先点击"添加照片"按钮,选择要上传的照片</div>
<div class="fieldset" id="fsUploadProgress">
</div>
</div>
<div id="divMovieContainer">
<a οnclick="swfu.startUpload();" class="upload_disbutton" id="upload">开始上传</a>
</div>
<div>
</div>
<input type="hidden" id="level" value="2">
<input type="hidden" name="uid" value="{$userid}" id="uid">
</form>
</div>
<script type="text/javascript">
var swfu;
var settings = {
flash_url : "swfupload/swfupload.swf", //上传的Flash
upload_url: "http://www.domain.com/upload_batch.php", //处理上传请求的服务器端脚本URL
post_params: {"PHPSESSID" : "<?php echo session_id(); ?>"}, //开辟了一个新的Session进程
file_size_limit : "5 MB", //上传文件体积上限,单位MB
file_types : "*.jpg;*.gif;*.png;*.jpeg", //允许上传的文件类型 用 ; 号分割
file_types_description : "All Files", //文件类型描述
file_upload_limit : 100, //限定用户一次性最多上传多少个文件,在上传过程中,该数字会累加。0 则表示没有限制
file_queue_limit : 20, //上传队列数量限制
debug: false, //是否显示调试信息,上线后记得将此关闭
//添加照片的按钮设置
button_image_url: "swfupload/button.png", //按钮的图片
button_width: "110",
button_height: "30",
button_placeholder_id: "spanButtonPlaceHolder",
button_text: '',
button_text_style: ".add_button {display:block; float:left; background:#000000; font-size:13px; font-weight:bold; padding-left:30px; width:66px; height:30px; line-height:30px; color:#000; cursor:pointer; text-decoration:none; margin-left:5px; cursor:pointer; }",
button_text_left_padding: 12,
button_text_top_padding: 3,
button_window_mode: SWFUpload.WINDOW_MODE.TRANSPARENT,
button_cursor: SWFUpload.CURSOR.HAND, //鼠标手型
//这些事件处理函数定义在:handlers.js 文件中
file_queued_handler : fileQueued, //文件成功选择后触发的事件处理函数
file_dialog_start_handler: fileDialogStart,
file_queue_error_handler : fileQueueError, //文件选择失败后触发事件(类型不对、大小不对等等)
file_dialog_complete_handler : fileDialogComplete, //文件选择窗口关闭时触发的事件处理函数
upload_start_handler : uploadStart, //开始上传文件前触发的事件处理函数
upload_progress_handler : uploadProgress, //文件上传过程中触发的事件处理函数
upload_error_handler : uploadError, //文件传输过程中出错触发的事件处理函数
upload_success_handler : uploadSuccess, //文件上传成功后触发的事件处理函数
upload_complete_handler : uploadComplete //文件上传完成后触发的事件处理函数
};
//初始化和设置
function initSWF() {
swfu = new SWFUpload(settings);
}
function setPost() //动态传递参数
{
var aid = document.getElementById('picgid').value; //相册ID
var uid = document.getElementById('uid').value; //上传照片用户ID
swfu.addPostParam("gid", gid);
swfu.addPostParam("uid", uid);//动态修改SWFUpload初始化设置中的post_params属性,其中所有的值都将被覆盖。
}
initSWF(); //初始化
</script>
二、页面效果图
当选择好多个文件后,点击开始上传,上传文件的过程中,每一次都会去执行后端的保存文件。
三、后端文件是PHP程序:upload_batch.php
<?php
// Work-around for setting up a session because Flash Player doesn't send the cookies
if (isset($_POST["PHPSESSID"])) {
session_id($_POST["PHPSESSID"]);
}
session_start();
if (!isset($_FILES["Filedata"]) || !is_uploaded_file($_FILES["Filedata"]["tmp_name"]) || $_FILES["Filedata"]["error"] != 0) {
echo "There was a problem with the upload";
}
$gid = empty($_POST['aid']) ? '0' : $_POST['aid'];
$uid = $_POST['uid'];
//判断目录是否存在
$user_path = 'user/'.substr($uid,-3).'/'.$uid;
if(!file_exists('/home/www/hoopchina/image/'.$user_path)) {
if(!file_exists('../image/user/'.substr($uid,-3))) {
mkdir('../image/user/'.substr($uid,-3),0777);
}
if(!file_exists('../image/'.$user_path)) {
mkdir('../image/'.$user_path,0777);
}
}
//上传保存的路径
//$save_path = "../images/";
$save_path = '../image/'.$user_path;
//上传文件赋值给$upload_file
$upload_file = $_FILES['Filedata'];
//获取文件类型
$file_info = pathinfo($upload_file['name']);
//获取文件扩展名
$file_ext = strtolower($file_info['extension']);
if ($file_ext == 'jpeg') { //类型转换
$file_ext = 'jpg';
}
if (!isset($upload_file)) {
handleError("未找到上传文件" . $upload_file['name']);
exit(0);
} else if (!isset($upload_file['name'])) {
handleError("文件未命名");
exit(0);
}
$upload_file['filename'] = time().'.'.$file_ext;
$upload_file['filenamebig'] = time().'big.'.$file_ext;
$upload_file['filenamesmall'] = time().'small.'.$file_ext;
if (!@move_uploaded_file($upload_file["tmp_name"], $save_path.'/'.$upload_file['filenamebig'])) {
handleError("文件上传失败");
exit(0);
} else {
//切割图片cut_photo($x,$y,$oldpic,$newpic)
cut_photo(130,180,$save_path.'/'.$upload_file['filenamebig'], $save_path.'/'.$upload_file['filenamesmall']);
if($file_ext == 'gif') { //是否为GIF动画
$fp = fopen($save_path.'/'.$upload_file['filenamebig'], 'rb');
$filecontent = fread($fp, filesize($save_path.'/'.$upload_file['filenamebig']));
fclose($fp);
strpos($filecontent,chr(0x21).chr(0xff).chr(0x0b).'NETSCAPE2.0') === FALSE ? $isgif = 0 : $isgif = 1;
if ($isgif) { //如果是多帧的,刚不用切割,直接copy
copy($save_path.'/'.$upload_file['filenamebig'],$save_path.'/'.$upload_file['filename']);
} else {
cut_photo(750,1500,$save_path.'/'.$upload_file['filenamebig'], $save_path.'/'.$upload_file['filename']);
}
} else {
cut_photo(750,1500,$save_path.'/'.$upload_file['filenamebig'], $save_path.'/'.$upload_file['filename']);
}
//将图片被切割为(750,1500)大小的路径写入数据库
$db_path = $user_path.'/'.$upload_file['filename'];
//计算图片大小,单位:KB
$file_size = ceil($upload_file['size']/1024);
//写入数据库
$db->query("INSERT INTO photo (pid, aid, uid, name, pic, dateline, size, hits) VALUES (NULL, '{$aid}', '{$uid}' , '".iconv('utf-8','gbk', $upload_file['name'])."', '{$db_path}', '".time()."', '{$file_size}', '0')"); //iconv是为了上传中文文件名乱码的问题
}
exit(0);
function handleError($message) {
echo $message;
}
?>
以上只是个人在项目中用到的基本方法,只是部分代码。如有不对处,欢迎大家拍砖。希望对有需要的筒子起个抛砖引玉的效果。
注: 在使用过会偶尔弹出“uncaught exception: call to SetPostParams failed ” 错误,经分析应该swfu还未完全加载,后将这个函数的调用放入handlers.js中fileDialogStart()函数中:
function fileDialogStart()
{
setPost();
}
再测试,一切正常。