Flex 的 FileReference.save() 只能在用户事件处理程序中调用 - 我该如何解决这个问题?

发布于 2024-09-10 16:07:35 字数 1350 浏览 4 评论 0原文

我需要在 Web 服务调用完成后调用 FileReference.save(),但此方法有一个限制:“在 Flash Player 中,您只能成功调用此方法来响应用户事件(例如,在事件处理程序中)对于鼠标单击或按键事件),否则调用此方法会导致 Flash Player 抛出 Error 异常。” (来自文档 这里

这个限制有点模糊。这是否意味着我只能从注册为某些类型的用户事件侦听器的事件处理函数中调用 FileReference.save() 方法?如果是这样,那么到底哪些用户事件是有效的? (也许有一个事件永远不会通过用户与我的应用程序的交互来调度,我可以为该事件类型注册一个事件处理函数,并从该函数内进行 save() 调用?)

我的困难是我不能安全地调用 FileReference.save() 方法,直到我的 Web 服务返回将用作 FileReference.save() 方法调用的参数的数据,因此触发 FileReference.save() 调用的事件实际上是 ResultEvent 而不是比用户事件,并且我对分派新的(虚假)用户事件类型持怀疑态度,以便能够触发 FileReference.save() 调用,除非它绝对是一个永远不会因实际情况而分派的用户事件用户与我的应用程序的交互。

简而言之,我现在正在做的是:我有一个函数被注册为按钮单击的处理程序。在此函数中,我进行 Web 服务调用以从服务器获取数据。我还有一个结果处理函数,当 Web 服务调用完成时会调用该函数,我想在此处调用 FileReference.save() 方法,因为此时我知道数据已准备好保存到一个文件。但上述限制阻止我这样做 - 我收到一个错误:

Error #2176: Certain actions, such as those that display a pop-up window, 
may only be invoked upon user interaction, for example by a mouse click 
or button press.

我尝试了很多方法来解决这个问题,例如使用 FileReference.save() 调用创建第二个鼠标单击事件处理程序函数并在之后调用它超时间隔(给网络服务时间来完成),但我不断遇到同样的错误——也许这种方法不起作用,因为第二个函数没有注册为用作其事件类型的事件侦听器争论。

我是 Flex 开发的新手,所以也许我只是没有以正确的方式思考这个问题。如果有人可以建议另一种方法,我将非常感激。预先感谢您的意见或建议。

——詹姆斯

I need to call FileReference.save() after a web service call has completed, but this method has a restriction: "In Flash Player, you can only call this method successfully in response to a user event (for example, in an event handler for a mouse click or keypress event). Otherwise, calling this method results in Flash Player throwing an Error exception." (from the documentation here)

This restriction is a bit vague. Does it mean that I can only call the FileReference.save() method from within an event handler function that is registered as a listener for certain types of user events? If so then exactly which user events are valid? (Perhaps there's an event that will never be dispatched by user interaction with my application and I could register an event handler function for that event type and make the save() call from within that function?)

My difficulty is that I can't safely call the FileReference.save() method until my web service returns with the data that will be used as the argument of the FileReference.save() method call, so the event that triggers the FileReference.save() call is actually a ResultEvent rather than a user event, and I'm leery of dispatching a new (faux) user event type in order to be able to trigger the FileReference.save() call unless it's definitely a user event that would never be dispatched as a result of actual user interaction with my application.

In a nutshell what I'm doing now is this: I have a function that is registered as a handler for a button click. In this function I make my web service call to fetch data from the server. I also have a result handler function which gets invoked when the web service call completes, and it's in here that I want to call the FileReference.save() method since it's at this point that I know that the data is ready to be saved to a file. But the aforementioned restriction is blocking me from doing this -- I get an error:

Error #2176: Certain actions, such as those that display a pop-up window, 
may only be invoked upon user interaction, for example by a mouse click 
or button press.

I've tried many things to get around this such as creating a second mouse click event handler function with the FileReference.save() call within and calling it after a timeout interval (to give the web service time to complete), but I keep running into the same error -- maybe that approach doesn't work since the second function isn't registered as an event listener for the event type used as its argument.

I'm new to Flex development so perhaps I'm just not thinking about this in the right way. If anyone can suggest another approach I'd really appreciate it. Thanks in advance for your comments or suggestions.

--James

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

一城柳絮吹成雪 2024-09-17 16:07:35

Adobe 这样做是作为一种安全措施,以确保用户是弄乱文件而不是潜在有害代码的人。我的理解是,他们通过只允许源自 UI 组件的(单击?)事件处理程序执行 FileReference 方法来强制执行此操作,因此以编程方式生成您自己的事件将不起作用,尽管我尚未尝试验证这一点。不幸的是,我发现的最佳解决方案是稍微重新设计 UI 以符合此限制。在您的特定情况下,您可以通过一个按钮进行两次单击,其中显示“准备下载”之类的内容,在 Web 服务完成后该按钮将更改为“下载文件”。从用户的角度来看,这不太理想,但我认为除非您能够在显示触发 FileReference.save() 调用的按钮之前以某种方式完成 Web 服务调用,否则没有什么可以做的。

Adobe does this as a sort of security measure to ensure users are the ones messing with files rather than potentially harmful code. My understanding is that they enforce this by only allowing handlers of (click?) events that originate from UI components to execute the FileReference methods, so generating your own events programmatically will not work, although I have not tried to verify this. Unfortunately the best resolution I've found is to re-work the UI a bit to conform to this constraint. In your particular situation, you could make this a two click process with a button that says something like "Prepare Download", which changes to "Download File" after the web service is complete. This is less than ideal from a user perspective, but I don't think there's much else that can be done unless you can somehow complete your web service call prior to displaying the button that triggers the FileReference.save() call.

猫烠⑼条掵仅有一顆心 2024-09-17 16:07:35

经过一番努力后,我找到了一个解决方法:您可以同时使用 mouseDown 和 mouseUp 事件,而不仅仅是单击。

例如:
s:按钮
mouseDown="prepare_PDF()"
mouseUp="save_PDF()"

对我来说效果很好!

快乐编码!

——托马斯

After struggling for that for well, a couple hours I found a workaround: you can use both mouseDown AND mouseUp events instead of just click.

For instance:
s:Button
mouseDown="prepare_PDF()"
mouseUp="save_PDF()"

Works fine for me!

Happy coding!

--Thomas

故事还在继续 2024-09-17 16:07:35

作为解决方法,我使用了ExternalInterface 类。我用这段代码创建了一个 JavaScript 函数

function downloadFile (url) {
            window.open(url);
        }

,在 AS3 中我称之为

var url = 'www.example.com/downloadfile.php?file_id=xxx';
ExternalInterface.call('downloadAttachmentFile', url);

So,我将文件处理转移到 JS/HTML。

As a workaround I used the ExternalInterface class. I created a javascript function with this code

function downloadFile (url) {
            window.open(url);
        }

An in AS3 I call

var url = 'www.example.com/downloadfile.php?file_id=xxx';
ExternalInterface.call('downloadAttachmentFile', url);

So with that I transfer the file handling to JS/HTML.

难理解 2024-09-17 16:07:35

这是对 Thomas 答案的评论(我还没有足够的 XP 来发表评论): mousedownmouseup 解决方法效果很好。请注意,如果您在 prepare_PDF() 中进行了任何需要在 save_PDF() 中“撤消”的更改,那么最好在 save_PDF() 中调用该代码>mouseout 事件也是如此,因为可能存在用户 mousedown 位于按钮上,但随后将鼠标移离按钮的情况。

这与我的案例特别相关,当用户单击下载按钮(触发 .save() 调用)时,我们会增加图像上水印的大小。我在 mousedownmouseout 事件上将水印的大小减小到正常大小。

This is a comment on Thomas' answer (I don't have enough XP to comment yet): The mousedown and mouseup workaround works nicely. Just a note that if you make any changes in prepare_PDF() that need 'undoing' in save_PDF(), then its a good idea to call that code on the mouseout event as well, since there might be a case that the user mousedown's on the button, but then moves the mouse away from the button.

This was particularly relevant for my case, in which we increase the size of a watermark on an image when the user clicks the download button (that triggers the .save() call). I reduce the size of the watermark down to normal on the mousedown and mouseout events.

非要怀念 2024-09-17 16:07:35

我也遇到了同样的问题,我选择使用 flash.net 方法。从动作脚本调用 flash.net.navigateToURL(url); 或从 mxml 调用 navigateToURL(url);

I had this same issue, I chose to use flash.net methods. Call flash.net.navigateToURL(url); from an actionscript or navigateToURL(url); from mxml.

满栀 2024-09-17 16:07:35

我解决这个问题的方法是显示带有匿名函数的警报消息,这样我就不必创建按钮。

Alert.show("Do you wish to download the file?", "Confirm", Alert.OK | Alert.CANCEL, this, function (eventObj:CloseEvent):void {
                                                                                                    if (eventObj.detail == Alert.OK) {
                                                                                                        fileReference.save(zipOut.byteArray, dateFormater_titulo.format(new Date ()) + ".zip");
                                                                                                    }//if
                                                                                                 }/*function*/, null, Alert.OK);

What i do to solve this is to show an alert message with an anonymous function so i don't have to create a button.

Alert.show("Do you wish to download the file?", "Confirm", Alert.OK | Alert.CANCEL, this, function (eventObj:CloseEvent):void {
                                                                                                    if (eventObj.detail == Alert.OK) {
                                                                                                        fileReference.save(zipOut.byteArray, dateFormater_titulo.format(new Date ()) + ".zip");
                                                                                                    }//if
                                                                                                 }/*function*/, null, Alert.OK);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文