将air中的文件(数据)拖拽到操作系统。想将文件从air中拖出,就用到文件承诺。

文件承诺是指,当您希望用户能拖放还不存在或位于其他位置(不在您的本地机器上)的文件时,您放在剪贴板上的内容。例如,远程服务器上的文件,或是您只希望在用户尝试拖放它们时生成的文件(如 CSV 文件)。文件承诺并不是实际存在的文件;正如其名,它表示在用户选择放下位置后,在之后的某个时刻提供文件的承诺。

在AIR中,并没有一个直接的文件承诺类,而是提供了一个IFilePromise的接口。就是说,只要实现这个接口的类,就具备了文件承诺的功能。这对于初学者有些不便,不像File类那样直接就可以使用,不过这也提供了更大的扩展性。你可以为你的各种数据实现文件承诺功能。虽然没有具体的文件承诺类,AIR也有一个类实现了IFilePromise的接口。就是 URLFilePromise类。

var cb:Clipboard = new Clipboard();
var items:Array = fileData.selectedItems;
var promises:Array = new Array();
for each (var item:Object in items) 
{
var fp:URLFilePromise = new URLFilePromise(); var req:URLRequest = new URLRequest(item.url); fp.request = req; fp.relativePath = item.name; promises.push(fp); } cb.setData(ClipboardFormats.FILE_PROMISE_LIST_FORMAT, promises); NativeDragManager.doDrag(fileData, cb);

以下是使用文件承诺时需要记住的几点:
文件承诺只适用于拖放操作(不适用于复制和粘贴)。不能将文件承诺放在普通剪贴板上供最终用户粘贴。(实际上,您可以这样操作,但 setData 将返回 false,表明这样操作无效。)
只能在 AIR 应用程序与本机文件系统之间使用文件承诺。不能使用文件承诺在 AIR 或本机应用程序之间拖放或复制和粘贴。
如果文件承诺由于任何原因失败,将从文件系统中自动删除不完整的文件,这样您的代码不必进行清理操作。不会删除之前下载的文件,并且仍将尝试后续下载。

从air中拖出的对象,用的比较多的就是位图。那么,我们就自定义一个位图的承诺类,让它实现IFilePromise接口。

package
{
    import flash.desktop.IFilePromise;
    import flash.display.BitmapData;
    import flash.display.JPEGEncoderOptions;
    import flash.events.ErrorEvent;
    import flash.utils.ByteArray;
    import flash.utils.IDataInput;
    
    /**
     * 
     * @author vini123
     *  实现了IFilePromise接口,是将air中的文件拖入到桌面的前提之一
     */    
    public class BitmapFilePromise implements IFilePromise
    {
        private var bitmapData:BitmapData;
        private var dataPath:String;
        
        /**
         * 
         * @param data 数据
         * @param path 文件名
         * 
         */        
        public function BitmapFilePromise(data:BitmapData , path:String)
        {
            bitmapData = data;
            dataPath = path;
        }
        
        public function get relativePath():String
        {
            return dataPath;
        }
        
        public function get isAsync():Boolean
        {
            return false;
        }
        
        public function open():IDataInput
        {
            var byteArray:ByteArray = new ByteArray();
            var jpgEncoder:JPEGEncoderOptions = new JPEGEncoderOptions();
            bitmapData.encode(bitmapData.rect , jpgEncoder , byteArray);
            byteArray.position = 0;;
            return byteArray;
        }
        
        public function close():void
        {
            
        }
        
        public function reportError(e:ErrorEvent):void
        {
            
        }
    }
}

拖拽是通过鼠标事件MOUSE_DOWN来触发,通过NativeDragManager.doDrag启动的。这个过程中,先需要创建剪贴板Clipboard,然后向剪贴板中插入数据,插入的数据对应着类型:ClipboardFormats.FILE_PROMISE_LIST_FORMAT,数据是一个包含实现了IFilePromise的数组。

完整代码:

package
{
    import flash.desktop.Clipboard;
    import flash.desktop.ClipboardFormats;
    import flash.desktop.NativeDragManager;
    import flash.display.Bitmap;
    import flash.display.Loader;
    import flash.display.Sprite;
    import flash.display.StageAlign;
    import flash.display.StageScaleMode;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.geom.Point;
    import flash.net.URLRequest;
    
    [SWF(width = "720" , height = "450" , frameRate="30")]
    public class DragFileToOs extends Sprite
    {
        private var textArea:TextArea;
        private var bitmap:Bitmap;
        private var container:Sprite;
        
        public function DragFileToOs()
        {
            stage.scaleMode = StageScaleMode.NO_SCALE;
            stage.align = StageAlign.TOP_LEFT;
            stage.addEventListener(Event.RESIZE , resizeHandler);
            
            initialize();
        }
        
        private function initialize():void
        {
            textArea = new TextArea("微软雅黑" , 12 , 0xff0000 , stage.stageWidth - 16 , stage.stageHeight - 16 );
            addChild(textArea);
            textArea.x = textArea.y = 8;
            
            loadFile();
        }
        
        private function loadFile():void
        {
            var loader:Loader = new Loader();
            loader.contentLoaderInfo.addEventListener(Event.COMPLETE , completeHandler);
            loader.load(new URLRequest("http://img.zcool.cn/community/01be3a554344dc0000002b01013da7.jpg"));
        }
        
        private function completeHandler(e:Event):void
        {
            bitmap = e.target.content as Bitmap;
            
            if(!container)
            {
                container = new Sprite();
                addChild(container);
            }
            container.addChild(bitmap);
            resizeBitmap();
            
            container.addEventListener(MouseEvent.MOUSE_DOWN , mouseDownHandler);
        }
        
        private function mouseDownHandler(e:MouseEvent):void
        {
            var bitmapFilePromise:BitmapFilePromise = new BitmapFilePromise(bitmap.bitmapData , "vini.jpg");
            var clipBoard:Clipboard = new Clipboard();
            clipBoard.setData(ClipboardFormats.FILE_PROMISE_LIST_FORMAT , [bitmapFilePromise]);
            NativeDragManager.doDrag(container , clipBoard, bitmap.bitmapData , new Point(-bitmap.width * 0.5 , -bitmap.height * 0.5));
        }
        
        private function resizeHandler(e:Event):void
        {
            if(textArea)
            {
                textArea.x = stage.stageWidth * 0.5 - textArea.width * 0.5;
                textArea.y = stage.stageHeight * 0.5 - textArea.height * 0.5;
            }
            resizeBitmapPos();
        }
        
        private function resizeBitmapPos():void
        {
            if(container)
            {
                container.x = stage.stageWidth * 0.5 - container.width * 0.5;
                container.y = stage.stageHeight * 0.5 - container.height * 0.5;
            }
        }
        
        private function resizeBitmap():void
        {
            if(container)
            {
                if(container.width/container.height > (textArea.width - 3)/(textArea.height - 3))
                {
                    container.width = textArea.width - 3;
                    container.scaleY = container.scaleX;
                }
                else
                {
                    container.height = textArea.height - 3;
                    container.scaleX = container.scaleY;
                }
                resizeBitmapPos();
            }
        }
    }
}

import flash.display.Sprite;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
import flash.text.TextFormat;

class TextArea extends Sprite
{
    private var textField:TextField;
    private var textWidth:int;
    private var textHeight:int;
    private const PADDING:int = 8;
    
    public function TextArea(font:String , size:int , color:int , tw:int , th:int , bold:Boolean = false)
    {
        textField = new TextField();
        textField.autoSize = TextFieldAutoSize.LEFT;
        textField.defaultTextFormat = new TextFormat(font , size , color , bold);
        textField.wordWrap = true;
        textField.multiline = true;
        textField.width = tw - PADDING * 2;
        textField.height = th - PADDING * 2;
        addChild(textField);
        
        textField.x = PADDING;
        textField.y = PADDING;
        textWidth = tw;
        textHeight = th;
        mouseChildren = false;
        mouseEnabled = false;
        
        graphics.clear();
        graphics.lineStyle(2 , color );
        graphics.beginFill(color , 0);
        graphics.drawRect(0 , 0 , tw , th);
        graphics.endFill();
    }
    
    public function set text(value:String):void
    {
        textField.appendText(value + "\n");
        if(textField.height > (height - PADDING * 2))
        {
            textField.text = value;
        }
    }
    
    override public function get width():Number
    {
        return textWidth;
    }
    
    override public function get height():Number
    {
        return textHeight;
    }
}

参考网站:http://www.adobe.com/cn/devnet/air/flex/articles/using_file_promises.html