跨域ExternalInterface“在NPObject上调用方法时出错”

19

我正在尝试通过跨域的ExternalInterface启用Javascript和Flash之间的通信。当Javascript位于与SWF相同的域中时,Javascript可以正常工作。但在某些情况下,HTML位于域A上,而Javascript和Flash都位于域B上。我已经完成了以下所有操作:

  • 嵌入标签具有allowScriptAccess="always"属性(对象也有该属性)
  • 我的SWF文件的Actionscript使用了Security.allowDomain("*")
  • 我的SWF还调用了Security.allowInsecureDomain("*")
  • 域A和域B都有一个/crossdomain.xml文件,其中包含allow-access-from domain="*"

SWF能够调用页面上的Javascript,但是当我使用Javascript调用由ExternalInterface公开的函数时,出现以下错误:

调用NPObject的方法时发生错误! [插件异常:Actionscript 中的错误。 使用try / catch块查找错误.]

这是ActionScript 2,因此不提供ExternalInterface.marshallExceptions


你是加载了一个以上的swf吗?还是在域A上(与HTML一起)加载了位于域B上的你的swf? - Alex Jillard
Alex -- 很好,我没提到那点。来自域 B 的 JavaScript 加载了一个来自域 B 的 SWF,而该 SWF 又加载了第二个来自域 B 的 SWF。这个加载似乎有效,但我不能确定,因为我无法与 SWF 进行交互。 - Josh
6个回答

20

您只需要两个东西才能让它起作用:

1)allowscriptaccess=always 将允许您的swf向页面发送信息

2)System.security.allowDomain("yourhtmldomain.com");

请注意,AS2中使用的是 System.security.allowDomain(),与AS3或上面所写的不同。

以上第2点允许位于domainA上的HTML页面调用位于domainB上的swf文件中的内容。

这里您js所在的域名并不重要,因为浏览器将其嵌入到domainA上,脚本在domainA中执行。

crossdomain.xml主要用于加载远程文件,而您并没有这样做,因此如果愿意,可以将其删除。 (而且您可能不希望在主域上放置一个带有allow="*"的crossdomain.xml文件,这是非常糟糕的做法)


1
奇怪的事情。我的SWF和JS/HTML都在同一页上,但是这个异常仍然存在:( - DataGreed

1

对我来说,原因有几个(我正在使用uploadify):

1. HTTP服务器没有权限将文件写入目标位置

2. swfobject(Flash)没有跨域访问权限

解决方案:

HTML中的object标签必须具有allowScriptAccess="always",可以通过设置参数来实现。

$('#file_upload').uploadifySettings('scriptAccess', 'always')
than flash object must have:
import flash.system.Security;
Security.allowDomain('remotedomain.com'); 

可以通过使用此参数编译源代码来完成,我有这个,如果您需要,请写信给我并注明uploadify主题。 然后远程服务器,在页面中包含Flash,必须在根目录下具有类似以下内容的crossdomain.xml文件:

<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">

1

由于您正在加载多个swf文件,因此您可能需要在加载到域B上的每个swf中包含安全设置。

您还可能需要具有适当安全设置的加载器上下文。

import flash.system.LoaderContext;
import flash.system.ApplicationDomain;
import flash.system.Security;
import flash.system.SecurityDomain;
import flash.net.URLRequest;
import flash.net.URLLoader;

var context:LoaderContext = new LoaderContext(true, ApplicationDomain.currentDomain, (Security.sandboxType == Security.REMOTE) ? SecurityDomain.currentDomain : null);
var l:Loader = new Loader();
l.load(new URLRequest("http://example.com/myswf.swf"), context);

你好,我有同样的问题,每当我尝试在安全域中输入除NULL以外的内容时,就会出现错误:Error #2114: Parameter LoaderContext.securityDomain must be null。有什么建议吗? - Chen Harel

0

0
在我的情况下,是因为我修改了包含上传器div的DOM元素。
我使用了jquery hide()函数来隐藏包含上传器的div,当我意识到这导致了上述错误时,我尝试了一种不同的方法,即设置div的"float"属性。在这两种情况下,上传器都无法正常工作。
顺便说一句,似乎将包含上传器的div的宽度/高度设置为0不会导致错误发生。

1
注意,Flash知道它何时可见,因此通过DOM使电影不可见可能会立即停止Flash执行。 - Steven

0

我曾经遇到过同样的问题(allowDomain等都没问题),但是我发送了错误的参数给Flash - 只是从ajax调用中输出JSON。当我将该JSON放入""中,然后通过jQuery.parseJSON将其解析为JavaScript对象时,问题就解决了。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接