【问题标题】:How to send binary data from AS3 through Java to a filesystem?如何通过 Java 将二进制数据从 AS3 发送到文件系统?
【发布时间】:2012-04-23 05:12:35
【问题描述】:

我在 AS3 中有需要压缩的 XML 数据,在我的 Java Google App Engine servlet 上进行验证,然后保存到 Google Cloud Storage 中的文件中。稍后,该文件将由 AS3 客户端打开并解压缩。如果我使用纯 XML 或文本执行此过程,则该过程有效,但如果我 ByteArray#compress 数据,它会在 ByteArray#uncompress 期间因“解压缩数据时出错”而死。

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

从 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);
}

【问题讨论】:

  • 也许在解压缩之前尝试 bytes.position = 0?
  • 谢谢,但没有帮助。我尝试在压缩之后打印出字节的值,并在解压缩之前再次打印出 - 一半的符号已被问号替换。应该是编码吧?
  • 可能,我会查看(httpfox)发送到服务器的数据并与发送回的数据进行比较。
  • 一旦你运行压缩文件将不再是人类可读的。我能想到的一件快速的事情是尝试编写 xml 文件的字符串版本。 xml.toXMLString();
  • 这是人类可读的足以告诉它已经改变了。之前:·ÉI-K?ãRP°)ÈI,IË/Ê-¶34µÑGð@r?å©Åù¹©y©ÅÅÅvF6úÈ\°Öü?0?3Ôª?0Q?ÍuL?IXZê#I@?@Cmô!n? 6= 之后:??IK??RP?)?I,I?/?-?34??G?@r???????y???vF6??\????0?3 ???0Q??uL?IXZ?#I@?@Cm?!n

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


【解决方案1】:

这是我用来保存 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 中收到字符串后无法将其转换为二进制原始字节。

【讨论】:

  • 这只是我的压缩代码。正如我所提到的,这很好用 - 它以二进制格式发送,我遇到了问题。
【解决方案2】:

如果来自客户端,我会在您 POST 之前进行 base64 编码,以这种方式将其存储在 TextProerty 中,然后在客户端收到返回时进行 base64 解码/解压缩。如果你想将它作为二进制存储在 GAE 上,那么 base64 将它解码成一个 Blob。这是我使用您的代码拼凑起来的一些代码 sn-ps,以及我使用 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);
}

【讨论】:

  • 当我添加 Base64(它比普通二进制文件更紧凑)时,我最终在解压缩字符串的开头有额外的字符:"Wvalue thing>" 所以对 'new XML(new String(bytes))' 的调用会因格式错误的 XML 错误而终止。
  • 啊哈!终于找到了那个“W”的来源,它是bytes.writeObject(xml)添加的某种标题。如果我改用bytes.writeUTFBytes(xml),它就不会出现。
猜你喜欢
  • 2019-09-23
  • 2023-03-20
  • 1970-01-01
  • 1970-01-01
  • 2014-03-31
  • 2020-04-08
  • 2011-12-13
  • 2012-01-02
  • 1970-01-01
相关资源
最近更新 更多