为预加载器获取多个文件大小
好吧,当前我的SWF文件命中了一个php文件,它将查找我指定给它的所有文件,将它们的大小加在一起,然后将它们的组合大小作为一个数字返回。然后,我将此数字与ProgressEvent侦听器一起使用,以确定该网站特定部分的当前文件下载百分比。
很简单吧?好了,现在已经不可能使用该PHP文件了,我正在尝试在SWF内部进行所有操作,而不是让其通过外部脚本获取所需的数字。
在开始将文件加载到Flash之前,是否有任何好的方法来获取文件的大小?我确实需要预加载器是0到100%的预加载器,所以我需要在实际启动之前要下载的字节总数。
我曾经想到的是只是遍历包含文件URL的数组,开始加载它们,不显示任何加载就获取getTotalBytes,在第一个刻度上取消加载,将所有这些字节总数加起来,然后开始实际的下载过程。这种方法看起来很丑陋,并且会浪费大量时间,因为每次用户在网站上点击预加载器时,可能需要一两秒钟才能浏览所有文件,找到它们的总数,然后才开始下载。
是否有更好的解决方案来解决这些问题,而又无需超出闪存范围来获取这些文件的大小?
解决方案
回答
我们可以向服务器发出HTTP HEAD请求以获取文件。这将返回标题信息(包括文件大小),但不返回实际文件。然后,我们可以发出GET请求以加载文件。
http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html
(查看第9.4节HEAD)
我可能会做的是一个两层的进度条(带有2个进度条)。一个显示总进度(0到100%),一个显示每个文件的进度(下载每个文件时)。
这样,只要我们知道要加载的文件数,就可以完成总进度,而不必首先通过服务器获取文件大小。
迈克·钱伯斯
回答
Mike Chamber的想法将为我们提供帮助,但它仍然比在服务器端使用慢,因为无论如何我们都必须为每个文件提出请求。这基本上与我们自己说的相同,但是当我们明确要求标题时,它会稍微快一些。使用套接字执行请求:
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();