【问题标题】:Can Flash/AS3 load external images regardless of Content-Type?Flash/AS3 可以不考虑 Content-Type 加载外部图像吗?
【发布时间】:2011-06-21 00:27:18
【问题描述】:

免责声明:我不是 Flash 开发人员 但我正在尝试解决闪存问题。 请不要以为我很亲密 熟悉 AS 或 Flash,因为我是 不是。

我目前的困境是我托管的资源是application/octet-stream。在我的 Actionscript 代码中,我使用了一些库(据我所知)执行 new Image 并将资源加载到创建的对象中。

有一个方法,loadImage(url),它接受一个 url,你可以在其中向它提供图像的路径。

我无权访问loadImage 源代码,所以我不知道它究竟做了什么,但是工作的那个可以很好地加载图像,因为Content-Typeimage/jpeg。不工作的一个(我正在尝试修复的这个)不是因为 Content-Type 不同。

我想知道是否有人可以告诉我是否可以让 flash 基本上解析 URI,就好像它是 image/jpeg,而不管 Content-Type 是什么?

我无权访问源 目前的代码,但我只是 把它扔在那里以获得输入

如果需要,我明天会尝试获取一些源代码

编辑:好的,我现在可以访问源代码了。这是加载图像的部分:

postcardImage = new Image();
postcardImage.loadImage(imagePath);

我假设 Image 构造函数是 flash/AS 的原生构造函数,但我无法通过 google 搜索 loadImage 方法,所以它必须是自定义的,对吧?

或者 Image 构造函数本身可以是自定义的吗?原始Image 的扩展版本,带有loadImage 方法等?

不管怎样,有谁知道如何查看loadImage的源代码?

编辑#2:我做了一个ack-grep 并找到了库中定义的loadImage 方法的源代码:

public class Image extends Sprite {

    private var _source:String;
    private var _loader:Loader;
    private var _bmapData:BitmapData;
    private var _loadedBytes:Number;
    private var _totalBytes:Number;

    public function Image() {
        trace('IMAGE');
    }

    public function loadImage(s:String):void {
        _source = s;
        _loader = new Loader();
        _loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoaded);
        _loader.contentLoaderInfo.addEventListener(Event.INIT, onLoading);
        _loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, onProgress);
        _loader.load(new URLRequest(_source));

        function onProgress(e:ProgressEvent):void {
            _loadedBytes = e.target.bytesLoaded;
            dispatchEvent(new ProgressEvent(ProgressEvent.PROGRESS));
            if(!_totalBytes) {
                setTotalBytes(e.target.bytesTotal);
            }
        }

        function onLoading(e:Event):void {
            _loader.contentLoaderInfo.removeEventListener(Event.INIT, onLoading);
        }

        function onLoaded(e:Event):void {
            _bmapData = e.target.content.bitmapData;
            addChild(e.target.content);
            dispatchEvent(new Event(Event.COMPLETE));
            _loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, onLoaded);
        }
    }

    public function getBmapData():BitmapData {
        return _bmapData;
    }

    public function duplicate():Image {
        var dup:Image = new Image();
        dup.addChild(new Bitmap(_bmapData.clone()));
        return dup;
    }

    public function getLoadedBytes():Number {
        return _loadedBytes;
    }

    private function setTotalBytes(n:Number):void {
        _totalBytes = n;
        dispatchEvent(new Event("TOTALBYTES_SET"));
    }

    public function getTotalBytes():Number {
        return _totalBytes;
    }

}   

任何人都可以就我如何在这方面做loadBytes 提供建议吗?我正在考虑定义一个自定义方法,loadResource 或无论 Content-Type 如何都可以加载的东西......或者只是在当前 load 方法和内部创建一个可选参数,根据传递的内容进行分支。

【问题讨论】:

    标签: flash actionscript-3


    【解决方案1】:

    我最近一直在使用 ByteArray 方法,这听起来很有趣。我已经使用传递八位字节流的 URL 的方法修改了您的 Image 类。让我知道它是如何工作的!

    注意:我没有设置 _loadedBytes 和 _totalBytes 属性,而是绘制加载的图像以启用公共 'getBmapData' 方法。

    package {
    import flash.utils.ByteArray;
    import flash.net.URLStream;
    import flash.display.Bitmap;
    import flash.net.URLRequest;
    import flash.events.ProgressEvent;
    import flash.events.Event;
    import flash.display.BitmapData;
    import flash.display.Loader;
    import flash.display.Sprite;
    
    public class Image extends Sprite {
    
        private var _source : String;
        private var _loader : Loader;
        private var _bmapData : BitmapData;
        private var _loadedBytes : Number;
        private var _totalBytes : Number;
        private var _stream : URLStream;
        private var _bytes:ByteArray;
    
        public function Image() {
            trace('IMAGE');
        }
    
        public function loadImage(s : String) : void {
            _source = s;
            _loader = new Loader();
            _loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoaded);
            _loader.contentLoaderInfo.addEventListener(Event.INIT, onLoading);
            _loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, onProgress);
            _loader.load(new URLRequest(_source));
    
            function onProgress(e : ProgressEvent) : void {
                _loadedBytes = e.target.bytesLoaded;
                dispatchEvent(new ProgressEvent(ProgressEvent.PROGRESS));
                if(!_totalBytes) {
                    setTotalBytes(e.target.bytesTotal);
                }
            }
    
            function onLoading(e : Event) : void {
                _loader.contentLoaderInfo.removeEventListener(Event.INIT, onLoading);
            }
    
            function onLoaded(e : Event) : void {
                _bmapData = e.target.content.bitmapData;
                addChild(e.target.content);
                dispatchEvent(new Event(Event.COMPLETE));
                _loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, onLoaded);
            }
        }
    
    
    
        // ByteArray methods
        // adapted from Ted Patrick's 
        // http://ted.onflash.org/2007/12/progressive-image-loading-with.php
    
        public function loadBytes( s:String = "" ):void {
    
            // FOR EASY TESTING ONLY:
            if( s == "" ) s = "http://onflex.org/flexapps/applications/ProgressiveImageLoading/jpg.jpg";        
    
            // create URLStream with listeners
            _stream = new URLStream();
            _stream.addEventListener( ProgressEvent.PROGRESS , streamProgress );
    
            // Not firing, so lets not use it...
            //_stream.addEventListener( Event.COMPLETE , streamComplete );
    
    
            // create Loader for later
            _loader = new Loader();
    
            // create new ByteArray instance
            _bytes = new ByteArray();
    
            // go ahead and add it to the display list
            addChild( _loader );
    
            // start the show!
            _stream.load( new URLRequest(s) );
    
        }
    
        private function streamProgress(p : ProgressEvent) : void {
    
            trace("PROGRESS: ",  p.bytesLoaded, "of", p.bytesTotal );
    
            if( _stream.connected ) _stream.readBytes(_bytes, _bytes.length );
    
            if( _bytes.length == p.bytesTotal ) {
    
                // get rid of the event listeners to avoid re-firing 
                _stream.removeEventListener( ProgressEvent.PROGRESS , streamProgress ); 
    
                streamComplete();   
            }
        }
    
        private function streamComplete() : void {
            _loader.loadBytes( _bytes );
            _loader.contentLoaderInfo.addEventListener( Event.INIT, makeBitmapData );
        }
    
        private function makeBitmapData( e:Event ):void{
    
            _loader.contentLoaderInfo.removeEventListener( Event.INIT, makeBitmapData );
    
            // set the bitmapData for the other public methods
            _bmapData = new BitmapData(_loader.width, _loader.height );
            _bmapData.draw( this );
        }
    
        //-----
    
    
    
    
        public function getBmapData() : BitmapData {
            return _bmapData;
        }
    
        public function duplicate() : Image {
            var dup : Image = new Image();
            dup.addChild(new Bitmap(_bmapData.clone()));
            return dup;
        }
    
        public function getLoadedBytes() : Number {
            return _loadedBytes;
        }
    
        private function setTotalBytes(n : Number) : void {
            _totalBytes = n;
            dispatchEvent(new Event("TOTALBYTES_SET"));
        }
    
        public function getTotalBytes() : Number {
            return _totalBytes;
        }
    }  
    } 
    

    【讨论】:

    • 我在你的方法中放了一些console.logs,似乎streamProgress 正在发生(我用循环计数器做了5次console.log),但它从未真正完成。知道如何解决它永远不会完成的事实吗? PS - 如果有任何相关性,我正在 Chrome 中进行测试。
    • 另外,如果有任何因素,资源有一个Content-Length?也许我可以做一个字节数检查,如果它等于 HTTP 标头的 Content-Length 然后手动调用 Event.COMPLETE 回调?
    • 我的直觉是它没有完成,因为它是一个真正的流,而不仅仅是我在示例中使用的图像。您的第二条评论正是我要尝试的,当您获得预期的字节数时,可以调用“streamComplete(null)”。我寻找一个真正的八位字节流来尝试,但没有很快想出一个。随时给我写信:n at nickhubben dot com。
    • 抱歉,您将如何在流进度回调中进行字节长度检查?显然我不能做_bytes.length,因为它一直保持在0,直到它被填充和/或完整的回调完成......所以我必须使用另一个引用来检查字节长度?
    • 奥基多克。我刚刚编辑了上面的文件,因此它将字节添加到 ProgressEvent 处理程序中的 ByteArray。它还根据传入的流检查 ByteArray 的长度。它不喜欢我在调用“loadBytes”后立即尝试访问加载器的宽度/高度,所以我在加载器上使用 Complete 处理程序。
    【解决方案2】:

    简短回答:是的。

    我假设代码在幕后使用Loader 对象来执行实际的图像加载/检索(这是执行此类操作的标准方式)。加载器对象支持 PNG、JPEG 和 GIF(仅限第一帧)格式。

    现在,我不确定加载器是否使用响应的内容类型来猜测图像格式(我猜不是,但我可能是错的)。我知道 Loaders 有一个 loadBytes() 方法,它直接从原始字节加载图像——在这种情况下,嗅探 only 的格式使用图像的实际数据,因为没有直接涉及 HTTP 请求.因此,如果罪魁祸首确实是内容类型,您可以将图像作为原始数据单独加载,然后使用 loadBytes() 从该原始数据中获取图像对象,从而完全绕过该问题。

    当然,我们必须查看代码才能真正了解发生了什么。

    【讨论】:

    • 感谢您的回答。我找到了来源并将其粘贴在我的问题中。您对修改它的任何建议都会很棒。
    • 顺便说一下,这是我的尝试:pastie.org/private/yvuir4clnpdtolfb0yy65a
    • @meder: 即将到来:-) Image 是完全自定义的,顺便说一下——Flash 中没有Image 类(只有SpriteBitmap 等)
    • @meder:你的尝试看起来不错。有什么不正常的吗?
    • 我认为完整的事件处理程序永远不会被调用,因为它是一个流。我正在尝试 NHubben 的代码 atm。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-10
    • 2021-05-24
    • 1970-01-01
    • 1970-01-01
    • 2012-12-22
    • 2021-08-26
    相关资源
    最近更新 更多