flex 文件保存的问题

龙心 2010-09-28 12:58:33
大家好,刚接触flex,现在要求实现以下功能:
在页面上有一个保存按钮,点击按钮后弹出文件保存框,按用户选择的文件路径保存文件。
实现过程:
点击按钮后请求后台,获得从后台返回的数据,再调用FileReference的save()方法来实现。
这里遇到一个问题,我是在请求后台的响应函数里调用FileReference的save()方法的,这样flex会报一个错。
Error: Error #2176: 某些动作(如显示弹出窗口的动作)只能通过用户交互来调用,例如,单击鼠标或按下按钮。
一个解决方法:
在页面初始化的时候就取得想要保存的数据,并设成全局变量,然后调用FileReference的save()方法,
这样保存没有问题,但是客户要求在点击按钮的时候才去取数据。。。
请问有没有其他的方法或思路,十分感谢!
...全文
659 点赞 收藏 13
写回复
13 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
cottonsky 2011-04-21
[Quote=引用 3 楼 zyongsheng83 的回复:]

只能人为触发保存文件的操作,flash安全限制。
[/Quote]

确实,折腾了一天还是不得不服。最后的解决方法是,取得后台数据后弹出用户确认框,由用户点击确认按钮后开始下载工作。

参见:http://forums.adobe.com/message/2848670
回复
hjh811 2010-09-29
[Quote=引用 1 楼 popchild 的回复:]
在请求后台的响应函数加回调函数,执行访问数据库方法结束后调用FileReference的save()方法
[/Quote]1L方法可以的 如果数据量大 最好加上进度条,以免用户在瞎等待都还没弹出文件保存对话框
回复
龙心 2010-09-29
感谢各位的回答,现在找到了一种替代方法,正在测试,如果可以的话请大家帮忙看看有没有问题。代码等测试完后贴出来。
回复
龙心 2010-09-29
现在用的是一个替代方法,实现如下:
点击按钮调用(Flex端)
private function getCSVData():void
{
var request:URLRequest = new URLRequest("/工程名/getCSVData.do");
navigateToURL(request, '_self');
}
(java端)
public class GetCSVDataAction extends Action {
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) {
response.setContentType("application/octet-stream; charset=utf-8");
response.setHeader("Content-Disposition", "attachment;filename=Temp.csv");
PrintWriter out = null;
try {
out = response.getWriter();
//CSV数据作成
out.print("aaa,bbb,ccc,ddd");
} catch (Exception e) {
// 例外が無視
}
return null;
}
}
经过测试,这样做的话,在flex端点击按钮请求后台会直接打开文件下载框同时页面也不会跳转,大数据也支持。







回复
龙心 2010-09-29
[Quote=引用 5 楼 leemiki 的回复:]
不是客户只关心需求吗

还关心这个??厉害~~~~
[/Quote]
第一个原因是因为需要保存的数据量有时候会很大,如果每次都在页面加载的时候取得,会影响页面加载速度,造成用户体验不好。
第二个原因是因为我打开页面100次,但是我只有一次需要保存的话。我肯定希望只加载一次,而不是100次。
回复
les5332295 2010-09-28
请参考以下代码

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
layout="vertical"
verticalAlign="middle"
backgroundColor="white"
creationComplete="init();" viewSourceURL="srcview/index.html">

<mx:Script>
<![CDATA[
import mx.controls.Alert;
import mx.collections.ArrayCollection;
import flash.net.FileReference;

[Bindable]
[Embed('assets/disk.png')]
private var diskIcon:Class;

[Bindable]
private var arrColl:ArrayCollection;

/* URL of the file to download. */
private const FILE_URL:String = "http://blog.minidx.com/ext/downloading-files-in-flex-using-the-filereference-class/srcview/main.zip";

private var fileRef:FileReference;
private var urlReq:URLRequest;

private function init():void {
/* Initialize the array collection to an empty collection. */
arrColl = new ArrayCollection();

/* Set up the URL request to download the file specified by the FILE_URL variable. */
urlReq = new URLRequest(FILE_URL);

/* Define file reference object and add a bunch of event listeners. */
fileRef = new FileReference();
fileRef.addEventListener(Event.CANCEL, doEvent);
fileRef.addEventListener(Event.COMPLETE, doEvent);
fileRef.addEventListener(Event.OPEN, doEvent);
fileRef.addEventListener(Event.SELECT, doEvent);
fileRef.addEventListener(HTTPStatusEvent.HTTP_STATUS, doEvent);
fileRef.addEventListener(IOErrorEvent.IO_ERROR, doEvent);
fileRef.addEventListener(ProgressEvent.PROGRESS, doEvent);
fileRef.addEventListener(SecurityErrorEvent.SECURITY_ERROR, doEvent);
}

private function doEvent(evt:Event):void {
/* Create shortcut to the FileReference object. */
var fr:FileReference = evt.currentTarget as FileReference;

/* Add event order and type to the DataGrid control. */
arrColl.addItem({data:arrColl.length+1, type:evt.type, eventString:evt.toString()});

try {
/* Update the Model. */
fileRefModel.creationDate = fr.creationDate;
fileRefModel.creator = fr.creator;
fileRefModel.modificationDate = fr.modificationDate;
fileRefModel.name = fr.name;
fileRefModel.size = fr.size;
fileRefModel.type = fr.type;
/* Display the Text control. */
txt.visible = true;
} catch (err:*) {
/* uh oh, an error of sorts. */
}
}

private function downloadSourceCodeZip():void {
/* Clear existing array collection. */
arrColl = new ArrayCollection();
/* Hide the Text control. */
txt.visible = false;
/* Begin download. */
fileRef.download(urlReq);
}

private function showAlert(item:Object):void {
Alert.show(item.eventString, item.type);
}
]]>
</mx:Script>

<mx:Model id="fileRefModel">
<file>
<creationDate>{""}</creationDate>
<creator>{""}</creator>
<modificationDate>{""}</modificationDate>
<name>{""}</name>
<size>{""}</size>
<type>{""}</type>
</file>
</mx:Model>

<mx:Button id="downloadBtn" label="Download example source code" icon="{diskIcon}" click="downloadSourceCodeZip()" toolTip="{FILE_URL}" height="40" />

<mx:DataGrid id="debug" dataProvider="{arrColl}" width="{downloadBtn.width}" rowCount="5" rowHeight="22" itemClick="showAlert(event.currentTarget.selectedItem)">
<mx:columns>
<mx:DataGridColumn dataField="data" headerText="#" width="20" />
<mx:DataGridColumn dataField="type" headerText="Type" showDataTips="true" dataTipField="eventString" />
</mx:columns>
</mx:DataGrid>

<mx:Text id="txt" condenseWhite="true" visible="false">
<mx:text>
creationDate: {fileRefModel.creationDate}
creator: {fileRefModel.creator}
modificationDate: {fileRefModel.modificationDate}
name: {fileRefModel.name}
size: {fileRefModel.size}
type: {fileRefModel.type}
</mx:text>
</mx:Text>

</mx:Application>
回复
leemiki 2010-09-28
不是客户只关心需求吗

还关心这个??厉害~~~~
回复
leemiki 2010-09-28
对的!FileReference的save()是有安全限制的

正常途径无法自动调用,就像你说的必须通过用户交互

点击保存按钮的时候取数据有个问题,一旦数据量大就麻烦了

回复
只能人为触发保存文件的操作,flash安全限制。
回复
龙心 2010-09-28
点击按钮调用的函数:
private function getCSVData():void
{
var request:Request = new Request();
request.setEventType("eventType");
request.addEventListener("eventType", Handler);
...
//以上是请求后台代码
}
响应函数:
private function Handler(e:Event):void
{
var data:String = e.result;
var file:FileReference = new FileReference();
file.save(data, "Temp.csv");
//以上取得后台返回数据并打开文件保存框
}
感谢popchild的回答,但是我对回调函数不是很熟悉,能不能给出一个简单的思路。十分感谢!






回复
威尔亨特 2010-09-28
在请求后台的响应函数加回调函数,执行访问数据库方法结束后调用FileReference的save()方法
回复
相关推荐
发帖
Flex
创建于2007-12-13

4328

社区成员

多媒体/设计 Flex
申请成为版主
帖子事件
创建了帖子
2010-09-28 12:58
社区公告
暂无公告