Flex FileReference.save() может быть вызван только в обработчике событий пользователя - как я могу обойти это?
Мне нужно вызвать FileReference.save() после завершения сеанса веб-службы, но этот метод имеет ограничение: "В Flash Player вы можете использовать этот метод только в ответ на событие пользователя (например, в обработчик события для нажатия мыши или нажатия клавиши). В противном случае вызов этого метода приводит к тому, что Flash Player выбрасывает исключение ошибки." (из документации здесь)
Это ограничение немного расплывчато. Означает ли это, что я могу вызвать метод FileReference.save() из функции обработчика событий, которая зарегистрирована как слушатель для определенных типов пользовательских событий? Если да, то какие именно пользовательские события действительны? (Возможно, событие, которое никогда не будет отправлено взаимодействием пользователя с моим приложением, и я мог бы зарегистрировать функцию обработчика событий для этого типа события и сделать вызов save() из этой функции?)
Моя трудность заключается в том, что я не могу безопасно вызвать метод FileReference.save() до тех пор, пока моя веб-служба не вернется с данными, которые будут использоваться в качестве аргумента метода метода FileReference.save(), поэтому событие, которое запускает вызов FileReference.save() на самом деле является ResultEvent, а не пользовательским событием, и я не могу обработать новый тип событий (faux) пользователя, чтобы иметь возможность запускать вызов FileReference.save(), если он определенно не является которое никогда не будет отправлено в результате фактического взаимодействия с моим приложением.
Вкратце, что я делаю сейчас: у меня есть функция, зарегистрированная как обработчик для нажатия кнопки. В этой функции я делаю вызов веб-службы для извлечения данных с сервера. У меня также есть функция обработчика результатов, которая вызывается при завершении вызова веб-службы, и здесь я хочу вызвать метод 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, поэтому, возможно, я просто не думаю об этом правильно. Если кто-то может предложить другой подход, я бы очень признателен. Заранее благодарим за ваши комментарии или предложения.
- Джеймс
Ответы
Ответ 1
Adobe делает это как своего рода меру безопасности, чтобы гарантировать, что пользователи используют файлы, а не потенциально опасные коды. Мое понимание заключается в том, что они применяют это, только разрешая обработчики событий (click?), Которые исходят от компонентов пользовательского интерфейса, для выполнения методов FileReference, поэтому создание ваших собственных программ программно не будет работать, хотя я не пытался это проверить. К сожалению, лучшее разрешение, которое я нашел, - немного переработать интерфейс, чтобы соответствовать этому ограничению. В вашей конкретной ситуации вы можете сделать этот процесс с двумя нажатиями кнопки с надписью "Подготовка к загрузке", которая изменится на "Загрузить файл" после завершения веб-службы. Это меньше, чем идеально с точки зрения пользователя, но я не думаю, что многое другое можно сделать, если вы не сможете каким-то образом завершить свой вызов веб-службы до отображения кнопки, которая вызывает вызов FileReference.save().
Ответ 2
После того, как я боролся за это, пару часов я нашел обходной путь: вы можете использовать как mouseDown, так и mouseUp, а не просто щелкнуть.
Например:
s: Кнопка
MouseDown = "prepare_PDF()"
MouseUp = "save_PDF()"
Прекрасно работает для меня!
Счастливое кодирование!
- Томас
Ответ 3
В качестве обходного пути я использовал класс ExternalInterface. Я создал функцию javascript с этим кодом
function downloadFile (url) {
window.open(url);
}
А в AS3 я вызываю
var url = 'www.example.com/downloadfile.php?file_id=xxx';
ExternalInterface.call('downloadAttachmentFile', url);
Таким образом, я передаю обработку файла JS/HTML.
Ответ 4
Это комментарий к ответу Томаса (мне еще не хватает XP для комментариев): Обходной путь mousedown
и mouseup
работает хорошо. Просто обратите внимание, что если вы внесли какие-либо изменения в prepare_PDF()
, которые нуждаются в "отмене" в save_PDF()
, тогда неплохо было бы вызвать этот код в событии mouseout
, так как может быть случай, когда пользователь mousedown на кнопке, но затем отводит курсор от кнопки.
Это было особенно актуально для моего случая, когда мы увеличиваем размер водяного знака на изображении, когда пользователь нажимает кнопку загрузки (которая вызывает вызов .save()
). Я уменьшаю размер водяного знака до нормального значения событий mousedown
и mouseout
.
Ответ 5
У меня была эта же проблема, я решил использовать методы flash.net. Вызовите flash.net.navigateToURL(url);
из ActionScript или navigateToURL(url);
из mxml.
Ответ 6
Что я делаю, чтобы решить это, так это показать предупреждающее сообщение с анонимной функцией, поэтому мне не нужно создавать кнопку.
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);