您的位置:首页 > 其它

发送和读取数据

2012-10-08 08:59 239 查看
转自:《Actionscript3.0 CookBook》

19.0.发送和读取数据

简介

很多情况下我们需要发送数据到flash或从flash中读取数值,比如:

1.发送表单数据到服务端脚本以便存储到数据库;

2.发送电子邮件数据给服务端发送电子邮件;

3.从文本文件中读取数据;

4.从服务器端读取数据,这些数据可能来自于数据库;

5.发送数据给服务端处理并返回结果,比如说用户登陆界面

当从一个URL中读取数据时,Flash播放器会把数据转换成以下三种形式之一:文本形式,原始二进制数据,或URL编码变量,

URL-编码遵循以下规则:

1.每个变量名用=号与其值相关联,=号两边没有空格

2.变量值被Flash读取后都被转换为字符串,如artist=Picasso.

3.当有多个名称/值对时,每一对都用&符号分开,如artist=Picasso&type=painting.

4.空格被替换成+符号,不是%20,比如title=The+Old+Guitarist. (空格和%20 也可以用,但是用+ 兼容性更好

5.除了数字和字母,如空格都被转换成十六进制的转义序列,例如,"L'Atelier" 被转换成L%27Atelier (%27 就是单引号),看下面的转义序列表



看下面的一个URL-编码格式的变量:

artist=Picasso&type=painting&title=Guernica&room=L%27Atelier

在ActionScript 3.0里发送和读取的数据都会被改变。LoadVars类已经被flash.net的URLLoader所代

替。URLLoader 支持新的字符集映射,他们是URLRequest, URLVariables, 和URLStream 。这些类提供了比以前更强大更灵活的处理能力。

有一些是没有改变的,比如读取的数据依然遵循Flash 播放器标准安全沙漏体系,也就是说读取的数据文件或脚本必须和flash 在同一个域内。

19.1.从文本文件中读取数据

问题

我想读取外部的文本文件的内容到flash上。

解决办法

使用URLLoader.load( )方法和DataFormat.VARIABLES 读取URL-编码数据

讨论

读取URL-编码数据时应该使用URLLoader.load( )方法。

load( )方法需要一个URLRequest实例作为参数,该参数指向文本文件的URL,这个URL即可以是相对路径也可以是绝对路径。另外URLLoader 需要进行配置把文本数据解释成URL-编码变量。设置URLLoader的dataFormat属性为DataFormat.VARIABLES常量:

import flash.net.*;
// 首先创建URLLoader对象
var example:URLLoader = new URLLoader( );
// 进行设置
example.dataFormat = DataFormat.VARIABLES;
// 读取绝对路径的URL
example.load( new URLRequest( "http://www.darronschall.com/example.txt" ) );
// 读取相对路径的URL,文本文件和swf文件在同一个目录下
example.load( new URLRequest( "example.txt" ) );
假设文本文件的内容如下:

someText=testing&someNumber=123

一旦调用了load( )方法,Flash播放器就会试图读取URL的数据填充URLLoader的data属性。读取完成后,Flash会试图解码这些内容并发出complete事件,指示数据已经读取完毕。这时候你可以添加处理函数来处理了。如果读取失败,根据失败的原因URLLoader会发出不同类型的异常事件,因此除了监听完成事件,还要监听那些异常事件。

load( )调用引发的异常有:

httpStatus 当试图读取数据,Flash播放器检测出错误的HTTP请求时发出

ioError 当遇到致命错误导致下载终止时发出

securityError 当试图读取安全沙漏允许以外的域数据时发出

下面的例子演示监听各种事件:

package {
import flash.events.*;
import flash.net.*;
import flash.util.trace;
public class Example {
public function Example( ) {
// Create the URLLoader instance to be able to load data
var loader:URLLoader = new URLLoader( );
// Define the event handlers to listen for success and failure
loader.addEventListener( IOErrorEvent.IO_ERROR, handleIOError );
loader.addEventListener( HTTPStatusEvent.HTTP_STATUS, handleHttpStatus );
loader.addEventListener( SecurityErrorEvent.SECURITY_ERROR,handleSecurityError );
loader.addEventListener( Event.COMPLETE, handleComplete );
// Configure the loader to load URL-encoded variables
loader.dataFormat = DataFormat.VARIABLES;
// Attempt to load some data
loader.load( new URLRequest( "example.txt" ) );
}
function handleIOError( event:IOErrorEvent ):void {
trace( "Load failed: IO error: " + event.text );
}
function handleHttpStatus( event:HTTPStatusEvent ):void {
trace( "Load failed: HTTP Status = " + event.status );
}
function handleSecurityError( event:SecurityErrorEvent ):void {
trace( "Load failed: Security Error: " + event.text );
}
function handleComplete( event:Event ):Void {
trace( "The data has successfully loaded" );
}
}

如果读取成功,Flash播放器把数据存在URLLoader实例的data属性上并发出complete事件。下面的例子演示处理complete事件:

function handleComplete( event:Event ):void {
// 把event target 转换为URLLoader
var loader:URLLoader = URLLoader( event.target );
// 输出获得的数据
trace( "someText = " + data.someText );
trace( "someNumber = " + data.someNumber );
}
假设文本文件的内容如下:

someText=ActionScript+3.0+Cookbook&someNumber=3

通过for...in

语句遍历所有读取的变量:

function handleComplete( event:Event ):void {
var loader:URLLoader = URLLoader( event.target );
// Use a for . . . in loop to loop over all of the variables that
// were loaded
for ( var property
:String in loader.data ) {
// property 就是data里的变量名
trace( property + " = " + loader.data[property] );
}
}


19.2.从服务端脚本中读取变量

问题

我想从服务端脚本(ColdFusion, Perl, PHP, etc.)中读取变量.

解决办法

使用URLLoader.load( )方法和DataFormat.VARIABLES 读取由服务端脚本产生的URL-编码数据

讨论

ActionScript读取服务端脚本数据和读取文本文件的操作是一样的,当这些数据是从服务端数据库或其他资源中产生时,脚本必须输出为URL-编码的数据才行,如果你采用perl脚本,输出为URL-编码,就不需要其他任何调整了,看下面的例子:

#!/usr/bin/perl
# In a more practical example this value would be retrieved
# from a database or other server-side resource.
$someText = "test";
# 定义Content-Type 头.
print "Content-Type: text/plain\n\n";
# Output the name-value pair.
print "someText=$someText";
ColdFusion:
<cfsetting enablecfoutputonly="yes">
<cfprocessingdirective suppresswhitespace="yes">
<cfset someText = "test">
<cfoutput>someText=#someText#</cfoutput>
</cfprocessingdirective>
PHP:
<?php
$someText = "test";
echo "someText=$someText";
?>
上面的每个脚本例子中都返回一个变量:someText,用下面的ActionScript代码读取这个变量:
package {
import flash.events.*;
import flash.net.*;
import flash.util.trace;
public class Example( ) {
public function Example( ) {
// 创建URLLoader实例
var loader:URLLoader = new URLLoader( );
// 定义事件处理函数
loader.addEventListener( Event.COMPLETE, handleComplete );
// 设置读取的是URL-编码变量
loader.dataFormat = DataFormat.VARIABLES;
// 尝试读取数据
loader.load( new URLRequest( "getSomeText.cfm" ) );
}
private function handleComplete( event:Event ):void {
var loader:URLLoader = URLLoader( event.target );
trace( "someText = " + loader.data.someText );
}
}
}
如果你事先不知道变量名,可以使用for...in语句遍历data。

19.3.读取文本块(包括HTML和XML)

问题

我想读取文本块,如HTML或XML.

解决办法

使用URLLoader.load( )和DataFormat.TEXT

讨论

ActionScript 3.0 处理数据的方式已经和ActionScript 1.0 和2.0完全不同了,在以前的版本中,LoadVars 实例有两个不同的回调函数用于处理通过URL读取的数据。当处理读取的数据时触发onLoad( )回调函数,当数据读取完成时触发onData( )回调函数。flash.net.URLLoader类和LoadVars类则不同,它只有一个complete事件和dataFormat属性用于决定如何解释这些下载的数据。dataFormat属性如果为DataFormat.TEXT,则会把数据解释为普通的文本内容,如果为DataFormat.VARIABLES则解释为URL-编码的变量,默认情况下,URLLoader把数据解释为文本。假设从外部读取一个名为example.html的HTML数据,内容大致如下:

<b>Title:</b> ActionScript 3.0 Cookbook<br />
<b>Authors:</b> Joey Lott, Darron Schall, Keith Peters<br />
<b>Publisher URL:</b> <a href="http://www.oreilly.com">www.oreilly.com</a>
下面的例子将读取并显示这些内容:

package {
import flash.display.*;
import flash.text.*;
import flash.events.*
import flash.net.*;
public class HTMLLoadingExample extends Sprite {
private var _output:TextField;
public function HTMLLoadingExample( ) {
initializeOutput( );
loadData( );
}
private function initializeOutput( ):void {
_output = new TextField( );
_output.width = stage.stageWidth;
_output.height = stage.stageHeight;
_output.html = true; // Enable HTML for the text field
addChild( _output );
}
private function loadData( ):void {
var loader:URLLoader = new URLLoader( );
// Instruct the loader to read the file as plain text - This line is not
// necessary because the dataFormat is DataFormat.TEXT by default.
loader.dataFormat = DataFormat.TEXT;
// Register an event handler for when the data is finished downloading
loader.addEventListener( Event.COMPLETE, handleComplete );
// Load the HTML text from the example.html file
loader.load( new URLRequest( "example.html" ) );
}
private function handleComplete( event:Event ):void {
var loader:URLLoader = URLLoader( event.target );
// Assign the htmlText of the text field to the HTML text that was contained
// in example.html. The data property of the URLLoader is the file contents.
_output.htmlText = loader.data;
}
}
}
data 属性的数据类型是根据dataFormat 属性的设置而决定的,如果设置为DataFormat.TEXT,则data 属性的值为String 类型,如果设置DataFormat.VARIABLES,则是Object 类型,如果设置为DataFormat.BINARY,则data 的数据类型为flash.util.ByteArray。

19.4.检测读取进度

问题

我想知道数据读取的进度

解决办法

监听URLLoader的progress事件

讨论

URLLoader类有个progress事件,当正在下载数据时该事件就会触发。Flash播放器传递一个flash.events.ProgressEvent实例给事件处理函数,以便检查该事件bytesLoaded和bytesTotal属性。bytesLoaded属性是指已经读取的数据量,bytesTotal属性是指总共要读取的数据量。

下面的代码演示如何监听progress事件:

package {
import flash.display.*;
import flash.text.*;
import flash.events.*
import flash.net.*;
public class CheckProgressExample extends Sprite {
private var _output:TextField;
public function CheckProgressExample( ) {
initializeOutput( );
loadData( );
}
private function initializeOutput( ):void {
_output = new TextField( );
_output.width = stage.stageWidth;
_output.height = stage.stageHeight;
addChild( _output );
}
private function loadData( ):void {
var loader:URLLoader = new URLLoader();
// Listen for the progress event to check download progress
loader.addEventListener( ProgressEvent.PROGRESS, handleProgress );
loader.load( new URLRequest( "example.txt" ) );
}
private function handleProgress( event:ProgressEvent ):void {
// Calculate the percentage by multiplying the loaded-to-total
// ratio by 100
var percent:Number = Math.round( event.bytesLoaded / event.bytesTotal * 100 );
_output.text = " Loaded: " + event.bytesLoaded + "\n"
+ " Total: " + event.bytesTotal + "\n"
+ "Percent: " + percent;
}
}
}
需要注意的是URLLoader 不能边下载边处理数据,如果想这样可以用URLStream,这将在下一节讨论。

19.5.边下载边访问数据

问题

我想边下载边访问数据

解决办法

使用flash.net.URLStream 实例可在下在过程中立即读取二进制数据

讨论

第19.4章讨论了如何检测数据下载进度,但是由于URLLoader类本身的限制,只能等数据全部下载完才能读取数据,要想边下载边读取可使用URLStream类代替之。URLStream 可以边下载边以二进制形式读取数据, URLLoader 的dataFormat 属性为DataFormat.BINARY时和URLStream非常类似,它们有相同的事件,关键的区别是处理progress事件的方式不同而已。

在URLLoader 中,progress 事件在检测多少已下载的数据或显示下载进度方面有用,而URLStream 中的progress 事件允许使用bytesAvailable 属性和下列方法如readInt( ), readByte( ),readBoolean( )检查下载的数据。当使用URLLoader 不是很有效时或访问的数据都是二进制时最好使用URLStream。

下面的例子代码使用URLStream 读取一个.txt 文件,访问文件中的字节数据:

package {
import flash.display.*;
import flash.events.*
import flash.net.*;
public class CheckProgressExample extends Sprite {
public function CheckProgressExample( ) {
var streamer:URLStream = new URLStream( );
// Listen for the progress event to act on data
// as it is received
streamer.addEventListener( ProgressEvent.PROGRESS, handleProgress );
streamer.load( new URLRequest( "example.txt" ) );
}
private function handleProgress( event:ProgressEvent ):void {
// Cast the target of the vent as a URLStream
var streamer:URLStream = URLStream( event.target );
// 遍历所有已读取得字节数据
while ( streamer.bytesAvailable > 0 ) {
// Read a byte value and output it to the console window
trace( "Read byte: " + streamer.readByte( ) );
}
}
}
}
从上面的代码中可以看到,在进行读之前最好检测下bytesAvailable 属性,如果读取的字节超出缓冲的结果则会抛出EOFError 异常。

19.6.发送数据给服务端脚本

问题

我想发送数据给服务端脚本

解决办法

创建一个包含数据的URLRequest实例,并用flash.net.sendToURL( )方法传递给服务端脚本,如果想在新的浏览器窗口中打开可使用flash.net.navigateToURL( )方法,如果想知道执行结果,可使用URLLoader.load( )方法。

讨论

如果不用处理结果,最好是用flash.net.sendToUrl( )方法发送数据,例如发送一个web表单数据,而服务端脚本处理后不用返回结果显示出来。但是sendToURL( )方法也就不会返回数据是否收到的确认消息了,因此在实际应用中并不很实用。如果只是想显示一个信息如"Thank you for submitting the form,"确认信息,表示服务端已成功收到,可使用URLLoader.load( )方法,3.12节和19.7节.都讨论过这个方法。

通过sendToUrl传递给服务端的URLRequest实例包含传递的数据以及传输方式,如果data属性设置为URLVariables实例,则发送名称/值对到服务器,也可以是flash.util.ByteArray,通过HTTPPOST 方式传递二进制数据到服务器, 或者是String 类型的数据作为XML-RPC ( 看http://www.xmlrpc.com)请求发送到服务器。

下面的代码演示:

function sendData( ):void {
// Create a request that sends data to the process.cfm page
var request:URLRequest = new URLRequest( "process.cfm" );
// Create some variables to send, someText and someNumber.
var variables:URLVariables = new URLVariables( );
variables.someText = "Some text to send";
variables.someNumber = 26.2;
// Set the data to be sent to the variables, created earlier
request.data = variables;
// Send the data to the script for processing
sendToURL( request );
}
传递给URLRequest的URL既可以是绝对地址也可以是相对地址,这可以通过Flash播放器安全沙漏进行管理,有关安全方面看第3.12节。

// 设置url属性为绝对地址
request.url = "http://www.darronschall.com/cgi-bin/submitVars.cgi";
// 设置为相对于swf 文件的地址
request.url = "cgi-bin/submitVars.cgi";
通过sendToURL( )方法发送的数据被服务器处理后,服务器返回的信息会被Flash播放器忽略掉,要想发送数据且打开指定的浏览器可使用navigateToURL( )方法,这个方法也sendToURL( )方法几乎一样,只是多了个参数,如果设为_blank即会在新的窗口显示响应结果,还可设置为_self 或_parent 。

// 在新的窗口中发送数据
navigateToURL( request, "_blank" );

如果想接收服务器返回的结果,可使用URLLoader.load( )方法(看3.12节和19.7节).默认情况下,使用sendToURL( ) 或navigateToURL( )方法,数据都是通过HTTP POST方法传输的,URLRequest的method属性指定数据传输的方式,如URLRequestMethod.GET指HTTP GET 和URLRequestMethod.POST指HTTP POST。

var request:URLRequest = new URLRequest( "cgi-bin/submit.cgi" );
// 创建发送的变量
var variables:URLVariables = new URLVariables( );
variables.someText = "Post me!";
request.data = variables;
// 设置传输方式HTTP POST
request.method = URLRequestMethod.POST;
// Send the request and open the response in a new window
navigateToURL( request, "_blank" );


19.7.发送变量并处理返回结果

问题

我想发送变量到服务器脚本,并处理返回的结果

解决办法

使用URLLoader.load( )方法且设置URLRequest实例的data属性

讨论

当需要处理服务器返回的结果时,应该使用URLLoader.load( )方法。比如一个flash的商店程序,它的商品分类都存在服务器数据库里,当用户点击一个分类,flash发送这个分类id给服务器脚本并返回这个分类的商品数据。URLLoader.load( ) 发送数据给服务器脚本的方式和sendToURL( ) ,navigateToURL( ) 是一样的,下面的完整例子发送数据到服务器脚本并返回URL-编码的值:

package {
import flash.display.*;
import flash.text.*;
import flash.events.*
import flash.net.*;
public class SendAndLoadExample extends Sprite {
private var _output:TextField;
public function SendAndLoadExample( ) {
initializeOutput( );
sendData( );
}
private function initializeOutput( ):void {
_output = new TextField();
_output.width = stage.stageWidth;
_output.height = stage.stageHeight;
addChild( output );
}
private function sendData( ):Void {
// Create a URLRequest to contain the data to send
// to process.cfm
var request:URLRequest = new URLRequest( "process.cfm" );
// Create name-value pairs to send to the server
var variables:URLVariables = new URLVariables( );
variables.method = "getProductDetail"
variables.productId = 2;
request.data = variables;
// Create a URLLoader to send the data and receive a
// response
var loader:URLLoader = new URLLoader( );
// Expect the script to return URL-encoded variables
loader.dataFormat = DataFormat.VARIABLES;
// Listen for the complete event to read the server response
loader.addEventListener( Event.COMPLETE, handleComplete );
// Send the data in the URLRequest off to the script
loader.load( request );
}
private function handleComplete( event:Event ):void {
var loader:URLLoader = URLLoader( event.target );
// Expect the script to return name and description variables.
// Display these values in a text field on the screen.
_output.text = "Name: " + loader.data.name + "\n"
+ "Description: " + loader.data.description;
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐