Flash + PHP实现文件上传

Flash8中提供了FileReference类,利用它我们就能使用Flash做文件上传的用户端界面,然后结合其他Web程序,比如PHP,ASP,JSP,C#等,就可以实现文件上传了.

先看看这个效果

效果展示

在这个例子中,我们使用Flash做界面,然后让用户从本机选择要上传到服务器的文件(这里限定为只传纯文本*.txt文件,其实是其他类型文件也可以上传,这里要演示,所以只传文本文件).另外,上传之后,我们再使用loadVars把上传的文件内容加载下来,并现在是在Flash里.

使用说明:

  1. 文件名不要使用中文!!!
  2. 点浏览按钮选择要上传的文件(这里限定为大小不超过1M的纯文本*.txt文件)
  3. 点上传按钮,上传到服务器,ProgressBar组件会显示上传进度
  4. 上传完成后会显示出[查看该文件内容按钮],点击它,会从服务器读取上传的文件
  5. 如果读取成功,则会在最下面出现TextArea组件,并展示加载的内容.
  6. 任何时候出现了错误,则可能会出现Alert组件并展示错误信息.

代码分析

这里的主要是利用FileReference类的相关属性和方法,选择上传的文件,然后服务器后台接收信息,并保存文件.

SWF里的ActionScript代码

AS Code
import flash.net.FileReference;
import mx.controls.Alert;
System.useCodepage = true;
var allTypes:Array = new Array ();
// 文件类型
var textTypes:Object = new Object ();
textTypes.description = "Text Files (*.txt)";
textTypes.extension = "*.txt";
allTypes.push (textTypes);
var host:String = "http://www.4nothing.net/flashexample/as-php/";
var listener:Object = new Object ();
// 当选中文件时
listener.onSelect = function (file:FileReference):Void 
{
	if (file.size > 1024 * 1024)
	{
		errLog ("文件超过了1M");
		path_txt.text = "请先选择要上传的文件";
		return;
	}
	path_txt.text = "你选择的文件是 [" + file.name + "]";
	upload_btn.enabled = true;
};
// 当取消时
listener.onCancel = function (file:FileReference):Void 
{
	path_txt.text = "请先选择要上传的文件";
	upload_btn.enabled = false;
};
// 上传开始时调用
listener.onOpen = function (file:FileReference):Void 
{
	showResult (false);
	browse_btn.enabled = false;
	upload_btn.enabled = false;
	my_pb.setProgress (0, 0);
};
// 上传中
listener.onProgress = function (file:FileReferencebytesLoaded:NumberbytesTotal:Number):Void 
{
	my_pb.setProgress (bytesLoadedbytesTotal);
};
// 结束
listener.onComplete = function (file:FileReference):Void 
{
	browse_btn.enabled = true;
	upload_btn.enabled = true;
	view_btn._visible = true;
};
// HTTP错误
listener.onHTTPError = function (file:FileReference):Void 
{
	errLog ("onHTTPError: " + file.name);
};
// IO错误
listener.onIOError = function (file:FileReference):Void 
{
	errLog ("onIOError: " + file.name);
};
// 安全限制
listener.onSecurityError = function (file:FileReference, errorString:String):Void 
{
	errLog ("onSecurityError: " + file.name + " errorString: " + errorString);
};
// 用户浏览和上传按钮的监听对象
var browseObj:Object = new Object ();
browseObj.click = function ()
{
	fileRef.browse (allTypes);
};
var uploadObj:Object = new Object ();
uploadObj.click = function ()
{
	if (!fileRef.upload (host + "upload.php"))
	{
		errLog ("Upload dialog failed to open.");
	}
};
// 查看文件内容
var my_lv:LoadVars = new LoadVars ();
my_lv.onLoad = function (success)
{
	if (success)
	{
		trace ("ok");
		trace (this["content"]);
		if (Number (this["code"]) == 1)
		{
			content_txt._visible = true;
			content_txt.text = this["content"];
		}
		else
		{
			errLog ("获取信息失败!");
		}
	}
	else
	{
		trace ("error");
		errLog ("获取信息失败le!");
	}
	view_btn.enabled = true;
	browse_btn.enabled = true;
	upload_btn.enabled = true;
};
var viewObj:Object = new Object ();
viewObj.click = function ()
{
	view_btn.enabled = false;
	browse_btn.enabled = false;
	upload_btn.enabled = false;
	my_lv.load (host+"checkfile.php?filename=" + fileRef.name + "&time=" + getDateStr ());
};
function getDateStr ():String
{
	return new Date ().toString ();
}
var fileRef:FileReference = new FileReference ();
// 隐藏查看按钮和内容面板
function showResult (flag:Boolean)
{
	view_btn._visible = false;
	content_txt._visible = false;
}
// 错误提示
function errLog (msg:String)
{
	Alert.show (msg, "出错了!"Alert.OK);
}
function init ()
{
	// 添加监听器
	fileRef.addListener (listener);
	browse_btn.addEventListener ("click", browseObj);
	upload_btn.addEventListener ("click", uploadObj);
	view_btn.addEventListener ("click", viewObj);
	path_txt.editable = false;
	path_txt.text = "请先选择要上传的文件";
	// 进度条信息
	my_pb.mode = "manual";
	my_pb.label = "上传进度:%1 / %2 字节";
	my_pb.labelPlacement = "top";
	upload_btn.enabled = false;
	showResult (false);
}
stop ();
init ();

因为基本都是使用的组件,所以使用的addEventListener比较多.不过难度并不大.

服务器端php代码

upload.php

PHP Code
error_reporting(E_ALL ^ E_NOTICE);

/** 
  *	通过SWF上传来的文件具有如下结构
  *$_FILES['Filedata']				-->名称都是Filedata,注意大小写
  *$_FILES['Filedata']['name']		-->上传的文件名,包括扩展名
  *$_FILES['Filedata']['type']		-->文件类型,不要把它跟文件扩展名混为一谈,另外这项内容不一定可用。
  *$_FILES['Filedata']['tmp_name']	-->保存在服务器上的临时文件名。因为PHP会把上传的文件先保存在临时文件夹内
  *$_FILES['Filedata']['size']		-->已上传文件大小
  *$_FILES['Filedata']['error']		-->出现的错误
 */
$file = $_FILES['Filedata'];
// 直接访问本页面而没有上传文件时退出
if(empty($file))
{
	exit();
}
$name = $file['name'];
// 获取扩展名
$ext = strrchr($name,'.');
if($ext === false)
{
	exit();
}
// 限定为txt
if($ext != ".txt")
{
	exit();
}

 //检查文件大小
if($file['size'] > 1024 * 1024)
{
	exit();
}
// 保存路径
$uploaddir = './upload/';
// 实际保存的文件信息
$uploadfile = $uploaddir . basename($name);
move_uploaded_file($file['tmp_name'], $uploadfile);
 

需要注意的一点就是Flash上传文件时,服务器端接收到的名称是$_FILES['Filedata'],然后其他操作,包括检验文件类型,文件大小,及相应的保存工作也是比较简单的.可能有人会说,这里为什么要再次检查文件大小,文件扩展名,因为我们要牢记一句话:客户端传递来的信息都是不安全的!

源文件下载

  1. FLA文件:as_php_upload.fla
  2. SWF文件:as_php_upload.swf

这里不提供php文件的下载,如果需要,你可以直接从本页上复制,或者Mail我,本页底端有我的邮箱.