如何将AS3中的二进制数据通过Java发送到文件系统?

时间:2012-04-10 21:34:02

标签: java actionscript-3 google-app-engine servlets google-cloud-storage

我在AS3中获得了需要压缩的XML数据,在我的Java Google App Engine servlet上验证,然后保存到Google云端存储中的文件中。之后该文件将由AS3客户端打开并解压缩。如果我使用普通的XML或文本来处理这个过程,但是如果我使用ByteArray#压缩数据,它会在ByteArray #uncompress中因“解压缩数据时出错”而死掉。

我已尝试在各个点设置内容类型和mime类型,以及使用Base64进行编码,但每次尝试似乎都以不同的方式中断,我从来没有得到与我发送的相同的XML。我是否需要使用multipart?我应该在服务器上压缩吗?这样做的最佳做法是什么?

从AS3发送数据:

// compress xml using zlib
var xml:XML = <contents><thing>value</thing></contents>;
var bytes:ByteArray = new ByteArray();
bytes.writeObject(xml);
bytes.position = 0;
bytes.compress();

var request:URLRequest = new URLRequest(url);
var urlVariables :URLVariables = new URLVariables();
urlVariables.filename = "somefile.bin";
urlVariables.contents = bytes;
request.data = urlVariables;
request.method = URLRequestMethod.POST;
loader = new URLLoader();
loader.load(request);

在Java servlet中接收它并创建文件:

public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
    String filename = req.getParameter("filename");
    byte[] contents = req.getParameter("contents").getBytes();

    GSFileOptionsBuilder optionsBuilder = new GSFileOptionsBuilder()
        .setBucket("bucketname")
        .setKey(filename)
        .setAcl("public-read")
        .setMimeType("binary/octet-stream");
    AppEngineFile writableFile = fileService.createNewGSFile(optionsBuilder.build());
    boolean lockForWrite = true;
    FileWriteChannel writeChannel = fileService.openWriteChannel(writableFile, lockForWrite);
    writeChannel.write(ByteBuffer.wrap(contents));
    writeChannel.closeFinally();
}

在AS3中打开新文件:

var url :String = "http://commondatastorage.googleapis.com/bucketname/somefile.bin";
var request:URLRequest = new URLRequest(url);
request.method = URLRequestMethod.GET;
loader = new URLLoader();
loader.addEventListener(Event.COMPLETE, handleComplete);
loader.load(request);

protected function handleComplete (event:Event):void {
    var bytes:ByteArray = new ByteArray();
    bytes.writeObject(event.target.data);

    // dies on this line with "There was an error decompressing the data."
    bytes.uncompress();

    var xml:XML = new XML(new String(bytes));
    trace(xml);
}

2 个答案:

答案 0 :(得分:0)

这是我用来保存xml的代码。我将数据发送给PHP,但我认为它会以同样的方式为您工作......我没有遇到任何麻烦。

var createXMLURL:URLRequest = new URLRequest("createXML.php");
createXMLURL.method = URLRequestMethod.POST;
var Variables:URLVariables = new URLVariables();
Variables.xmlString = xml.toXMLString();
Variables.filename = filename;
createXMLURL.data = Variables;
var loader:URLLoader = new URLLoader();
loader.dataFormat = "VARIABLES";
loader.addEventListener(Event.COMPLETE, xmlCreated);
loader.load(createXMLURL);

如果您对某些变量有什么疑问,请告诉我,因为我没有包含他们的声明(我认为很容易弄清楚)。

现在这不会像你要求的那样以二进制格式发送数据,但是我不知道为什么你在java中收到字符串后无法将字符串转换成二进制文件如果你真的需要原始字节。

答案 1 :(得分:0)

我会在POST之前进行base64编码,如果是从客户端,将其存储在TextProerty中,然后在客户端收到后进行base64解码/解压缩。如果要将它作为二进制文件存储在GAE上,则base64将其解码为Blob。以下是我使用您的代码拼凑在一起的一些代码片段,以及我使用HttpService进行类似的事情 - 事先道歉并未对其进行广泛校对。 HTH。

private var _serviceHttp:HTTPService = new HTTPService;

private function postBytes():void {
    var xml:XML = <contents><thing>value</thing></contents>;
    var bytes:ByteArray = new ByteArray();
    bytes.writeObject(xml);
    bytes.position = 0;
    bytes.compress();
    var enc:Base64Encoder = new Base64Encoder();
    enc.encodeBytes(bytes, 0, bytes.length);
    var myObj:Object = new Object();
    myObj["bytes"] = enc.toString();
    // myObj["other_variables"] = your_other_varaibles;
    _serviceHttp.method = "POST";
    _serviceHttp.resultFormat = "flashvars";
    _serviceHttp.url = your_url_here;
    _serviceHttp.addEventListener(ResultEvent.RESULT, urlHandler);
    _serviceHttp.addEventListener(FaultEvent.FAULT, urlErrorHandler);
    _serviceHttp.send(myObj);
}