1

我正在 AS3 中做一个项目,用户可以在其中设计一些东西并在之后订购。设计导出为 PDF、PNG 和 XML。这些文件我想保存在服务器上。在 MAMP 上一切正常,我得到了 HTTPStatus 200,请注意,我从 MAMP 运行我的 SWF,但是在远程服务器上成功访问了 php 脚本,并且文件也成功写入了远程服务器。但是,当我将 SWF 复制到远程服务器时,文件没有保存并且我得到 HTTPStatus 0。

在我使用的类中(参见下面的 AS3 代码),我使用 URLLoader 来获取以下一行 php 脚本:

<?php file_put_contents($_POST['location'] . $_POST['fileName'], base64_decode($_POST['fileData']));

这里是 AS3 类:

public class ServerConnection extends Sprite
{
    private var _files:Array = new Array();
    private var _fileNames:Array;
    private var _fileLocation:String = "";
    private var _scriptLocation:String;

    private var _fileSavesInProgress:Array = new Array();

    public function ServerConnection(scriptLocation:String = null, files:Array = null, fileNames:Array = null)
    {
        if (scriptLocation) setScriptLocation(scriptLocation);
        if (files) setFiles(files);
        if (fileNames) setFileNames(fileNames);
    }


    public function encodeFiles():void {
        for(var i:uint = 0; i < _files.length; i++) {
            _files[i] = encodeFile(_files[i]);
        }
    }
    public function encodeFile(byteArray:ByteArray):Base64Encoder {
        var base64:Base64Encoder = new Base64Encoder();
        base64.encodeBytes(byteArray);
        return base64;
    }

    public function saveFiles(location:String = null):void {
        if (location) setFileLocation(location);
        for(var i:uint = 0; i < _files.length; i++) {
            _files[i] = saveFile(_files[i], _fileNames[i]);
        }
    }
    public function saveFile(encodedFile:Base64Encoder, fileName:String = "test"):void {
        var data:URLVariables = new URLVariables();
        data.fileData = encodedFile;
        data.fileName = fileName;
        data.location = _fileLocation;
        this.dispatchEvent(new DebugEvent(DebugEvent.MESSAGE, "@serverConnection: a save file request was made for " + 
            fileName + "\n" +
            "url: " + _fileLocation + "\n" +
            " scriptLocation: " + _scriptLocation + "\n"
        ));

        var request:URLRequest = new URLRequest(_scriptLocation);
        request.method = URLRequestMethod.POST;
        request.data = data;

        var loader:URLLoader= new URLLoader();
        loader.addEventListener(Event.COMPLETE, function(e:Event):void {fileSaved(loader);});
        loader.addEventListener(HTTPStatusEvent.HTTP_STATUS, httpStatus);
        loader.addEventListener(IOErrorEvent.IO_ERROR, ioError);
        _fileSavesInProgress.push(loader);

        try {
            loader.load(request);
        } catch (e:*) {
            this.dispatchEvent(new DebugEvent(DebugEvent.MESSAGE, "@serverConnection: error:* = " + e + " \n"));
        }

        //navigateToURL(request);
    }

    public function displayObjectToPNG(displayObject:*, scale:Number = 1):ByteArray {
        var bmpData:BitmapData=new BitmapData(displayObject.width, displayObject.height, true, 0xFFFFFF);
        bmpData.draw(displayObject);

        var byteArray:ByteArray = PNGEncoder.encode(bmpData);
        return byteArray;
    }

    public function xmlToByteArray(xml:XML):ByteArray {
        var byteArray:ByteArray = new ByteArray();
        byteArray.writeUTFBytes(xml);
        return byteArray;
    }

    public function setScriptLocation(url:String):void {
        _scriptLocation = url;
    }

    public function setFileLocation(url:String):void {
        _fileLocation = url;
    }

    public function setFiles(array:Array, encode:Boolean = true):void {
        for each(var file:* in array) {
            for each(var type:XML in describeType(file).extendsClass.@type) { 
                if (type == "flash.display::DisplayObject") file = displayObjectToPNG(file);
            }
            if (typeof(file) == "xml") {
                file =  xmlToByteArray(file);
            }

            _files.push(file);
        }
        if (encode) encodeFiles();
    }

    public function setFileNames(array:Array):void {
        _fileNames = array;
    }


    // EVENTS
    private function httpStatus(e:HTTPStatusEvent):void {
        this.dispatchEvent(new DebugEvent(DebugEvent.MESSAGE, "@serverConnection: status = " + e.status + " \n"));
    }

    private function ioError(e:IOErrorEvent):void {
        this.dispatchEvent(new DebugEvent(DebugEvent.MESSAGE, "@serverConnection: IOErrorID = " + e.errorID + "  Message: "+ e.text + " \n"));
    }

    private function fileSaved(loader:URLLoader):void {
        this.dispatchEvent(new DebugEvent(DebugEvent.MESSAGE, "@serverConnection: file save completed. " + (_fileSavesInProgress.length -1) + " files to go \n"));
        _fileSavesInProgress.splice(_fileSavesInProgress.indexOf(loader), 1);

        if (_fileSavesInProgress.length == 0) {
            filesSaved();
        }
    }

    private function filesSaved():void {
        this.dispatchEvent(new DebugEvent(DebugEvent.MESSAGE, "@serverConnection: files saved \n"));
        this.dispatchEvent (new ClassAttributesLoaded(ClassAttributesLoaded.CLASS_ATTRIBUTES_LOADED));
    }

}

我这样实现

    var s:ServerConnection = new ServerConnection(
    CONSTANT.SAVE_FILE_SCRIPT_LOCATION, 
    [currentTemplate.getXML(), exampleTemplate, pdf.save(Method.LOCAL)], 
    [CONSTANT.PACKAGE_ID + ".xml", CONSTANT.PACKAGE_ID + ".png", CONSTANT.PACKAGE_ID + ".pdf"]
);
s.addEventListener(DebugEvent.MESSAGE, writeToDebug);
s.addEventListener(ClassAttributesLoaded.CLASS_ATTRIBUTES_LOADED, exit);
s.saveFiles(CONSTANT.RELATIVE_FILE_DIRECTORY);

当我更改 loader.load(request); 导航到URL(请求);代码确实有效。在本地和远程服务器上。出于明显的原因,在这种情况下我不能使用 navigateToURL。我确实认为 navigateToURL 确实有效并且 loader.load(request) 并没有说明问题的事实......但是什么?

我有点坚持这一点,并希望得到帮助。提前致谢!

PS:为了测试,我已将远程 DIR 的权限设置为 777。此外,文件已成功从 MAMP 保存到远程,如前所述。

4

1 回答 1

1

解决方案

经过长时间的研究,我找到了解决方案:将以下 crossdomain.xml 添加到我的网络服务器的根目录 (www.mysite.nl/)。

<?xml version="1.0" ?>

<cross-domain-policy>
    <site-control permitted-cross-domain-policies="master-only"/>
    <allow-access-from domain="*.mydomain.com" to-ports="*"/>
    <allow-http-request-headers-from domain="*.mydomain.com" headers="*"/>
</cross-domain-policy>

这不安全,因此如果您想使用此解决方案,请将“mydomain.com”更改为您要允许的特定域。所以解决了它。

我是如何得到答案的

我能够使用以下代码捕获错误:

loader.addEventListener(IOErrorEvent.IO_ERROR, handleSecurityError);

返回的错误如下: [SecurityErrorEvent type="securityError" bubbles=false cancelable=false eventPhase=2 text="Error #2048"]

请注意,通常错误包含: [SecurityErrorEvent type="securityError" bubbles=false cancelable=false eventPhase=2 text="Error #2048: Security Sandbox Violation : http://www.domain-a.com/url/file- a.swf无法从http://www.domain-b.com/url/file-b.swf加载数据"]

此错误通常通过加载安全策略来解决。查看有关如何使用安全策略的链接:http: //kb2.adobe.com/cps/142/tn_14213.html

但是在这种情况下,访问的 url 在同一个域中。(注意:同一个文件夹:D)所以最初我认为这无关紧要,因为没有联系其他域。但是在搜索了一周之后,我变得如此绝望,我无论如何都尝试了。

因此,将 crossdomain.xml 添加到我的服务器的根目录就解决了这个问题。

于 2012-08-14T18:49:42.970 回答