题
好吧,目前我的 SWF 命中了一个 php 文件,该文件将查找我指定的所有文件,将它们的大小加在一起,然后将它们的组合大小作为一个数字返回。然后,我将这个数字与 ProgressEvent 侦听器一起使用,以确定网站特定部分的当前文件下载百分比。
很简单吧?现在,使用该 PHP 文件是不可能的,我正在尝试在 SWF 内部执行所有操作,而不是让它通过外部脚本来获取我需要的数字。
在开始将文件加载到闪存之前,有什么好的方法可以获取文件的大小吗?我确实需要预加载器是 0 到 100% 的预加载器,因此我需要在实际开始之前下载的总字节数。
我的一个想法是遍历保存文件 URL 的数组,开始加载它们,getTotalBytes 而不显示任何加载,在第一个刻度上终止加载,将所有这些总字节数相加,然后开始实际的下载过程。这种方法看起来非常丑陋,而且会浪费大量时间,因为每次用户点击网站上的预加载器时,可能需要一两秒钟的时间来运行所有文件,找到它们的总数,然后真正开始下载。
有没有更好的解决方案来解决这个问题,而无需超出闪存来获取这些文件的大小?
解决方案
您可以向服务器发出 HTTP HEAD 请求以获取文件。这将返回标头信息(包括文件大小),但不返回实际文件。然后您可以发出 GET 请求来加载文件。
http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html
(查看第 9.4 节 HEAD)
我可能会做的是一个两层进度条(有 2 个进度条)。一个显示总体进度(0 到 100%),另一个显示每个文件的进度(下载每个文件时)。
这样,只要您知道要加载的文件数量,您就可以完成总进度,而无需首先访问服务器来获取文件大小。
迈克·钱伯斯
mesh@adobe.com
其他提示
Mike Chamber 的想法会对您有所帮助,但它仍然比使用服务器端的东西慢,因为无论如何您都必须对每个文件发出请求。它本质上与您自己所说的相同,但是当您明确要求标头时,它会稍微快一些。使用 Socket 来执行请求:
var socket : Socket = new Socket( ); socket.addEventListener( Event.CONNECT, connectHandler ); socket.addEventListener( ProgressEvent.SOCKET_DATA, dataHandler ); socket.connect( "yourserver.com", 80 ); function connectHandler( event : Event ) : void { var headers : String = "HEAD yourfilename.ext http/1.1\r\n"; headers += "Host: yourserver.com\r\n"; headers += "\r\n\r\n"; socket.writeUTFBytes( headers ); socket.flush( ); } function dataHandler( event : ProgressEvent ) : void { trace( "Received headers\n" ); trace( socket.readUTF( socket.bytesAvailable ) ); }
如果绝对有必要控制文件的加载方式,那么我相信 Mike Chambers 提出的发出 HTTP HEAD 请求的建议是正确的选择。
但是,除非有充分的理由不这样做,否则我只需开始立即加载所有文件,并从每个文件的 getBytesTotal 方法获取文件大小。由于 Flash 从浏览器获取其网络堆栈,因此实际同时加载的文件数量将符合(用户可定义的)浏览器设置。
以下仅用于示例目的。在实际情况中,我不会使用 Timer,我会使用一个数组或 XML 对象来使用 for 循环进行迭代,无论它工作得很好,而且基本上一旦到达循环末尾(例如if(i == (length - 1)) 让它调用开始实际预加载的功能,现在我们已经有了总数。现在我们再次迭代数组或 XML 对象,但这次我们仅在每个资源加载后执行此操作,而不是在 for 循环中执行。然后,该异步方法可以坐在那里比较它已加载的数据量,并将其除以之前找到的总数,从而得出百分比。
var totalBytes:Number = 0; var loader:Loader = new Loader(); var request:URLRequest = new URLRequest(); request.url = 'badfish.jpg'; var timer:Timer = new Timer(200); timer.addEventListener(TimerEvent.TIMER, onTimer); function onTimer(e:TimerEvent) { loader.load(request); loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, onProgress); } function onProgress(e:ProgressEvent):void { totalBytes+=e.bytesTotal; trace(e.bytesTotal,totalBytes); loader.contentLoaderInfo.removeEventListener(ProgressEvent.PROGRESS, onProgress); } timer.start();