How to best to cancel a Zend Form File Upload? - zend-form

I am experimenting with uploading files in a Zend_Form using the Zend_Form_Element_File doing something like this in my form so that the actual upload can be handled by my controller (which in my case is to eventually do some custom file re-naming on the fly).
$element = new Zend_Form_Element_File('Upload');
$element->setDestination(UPLOAD_PATH)
->setValueDisabled(true);
$submit = new Zend_Form_Element_Submit('submit');
In the controller action I then have (very simplified) code like the following which works well:
$form = new MyForm();
$this->view->form = $form;
if ($this->getRequest()->isPost()) {
$formData = $this->getRequest()->getPost();
if ($form->isValid($formData)) {
$form->Upload->receive();
$this->_redirect('/nextAction');
} else {
$form->populate($formData);
}
}
However (and here it comes) what I want to do is have a cancel button on my form handled like this:
[Form]
$cancel = new Zend_Form_Element_Submit('cancel');
[Controller]
if ($this->getRequest()->isPost()) {
$formData = $this->getRequest()->getPost();
$cancel = $this->getRequest()->getPost('cancel');
if ($cancel == 'Cancel') {
$this->_redirect('/nextAction');
}
if ($form->isValid($formData)) {
$form->Upload->receive();
$this->_redirect('/nextAction');
} else {
$form->populate($formData);
}
}
The trouble starts when the user selects a file via 'Upload' and then hits 'cancel' to exit out of the action. The form doesn't know the difference between 'Submit' and 'Cancel' and initiates the transfer from the browsers end. On the server end the receive() function isn't called and that hangs the entire process.
In this older (Non-Zend) SO question "Cancel a webform submit with php" the suggested answer is to have the cancel button in a separate form. I don't think that this is what I want to do in a Zend based system.
In this old (Zend) forum question "Zend Form Element File upload issues" the suggested answer for canceling an upload is to do something like this:
if ($cancel == 'Cancel') {
unlink($form->Upload->getValue());
$this->_redirect('/nextAction');
}
I have tried this and it seems to work, but I don't know why and when I look behind the curtains I actually see that it generates an error of the form:
Warning: unlink(<filename>): No such file or directory in <line in controller code where unlink() call is>
So my big question is what is the best way to be canceling out of the file upload? (and what does the unlink do - even with the error?)
Edit 3/3
To clarify, HTML form uploads are pretty dumb. If you have multiple submit buttons on a form that has a File element, then no matter what submit button you seem to use the file gets transferred to the temp upload directory on your server.
But Zend tries to be clever, it allows you to defer copying the file from the temp directory to the final destination through "setValueDisabled(true)" in the form and "receive()" in the controller.
However if you initiate an upload in the form, but do not call "receive() in the controller, then the entire Zend process seems to lock up (I get the browser continually announcing "loading" and doing nothing else).
I am looking for a Zend (or pure php) based solution to back out of the file upload on the server side, after the file has arrived in the temp directory, but before a call to "receive()" is required.
The "unlink" method seems to work, but it also throws a warning and as I have no real idea of why it works I am suspicious of what is actually going on.

Try if ($cancel->isChecked()) instead of if ($cancel == 'Cancel')
EDIT
This is how file uploads work. The form is submitted, and the browser sends the file, through HTTP to server. PHP sees a form with enctype "multipart/form-data" and a file element, and saves that file in a temporary location. At this point, if you call "Receive", it actually calls, behind the scenes, the PHP functions which move that file out of its temporary location.
Once you hit submit, the browser sends the file, whether you like it or not. You can choose to ignore the file, which is what it looks like you're trying to do. However, if ($cancel == 'Cancel'), doesn't look it will work because the value is case-sensitive. To avoid error-prone code like this, if ($cancel->isChecked()) is preferred.
Can you be a little more specific on what exactly you're trying to do?

Related

Playwright upload file on non-input element

So I'm currently trying to automate uploading a profile photo on an Electron App using Playwright and I'm running into issues with 'filechooser' event.
await windowA.click('data-testid');
const [fileChooser] = await Promise.all([
windowA.waitForEvent('filechooser'),
// windowA.locator('text=Edit').click(),
windowA.waitForTimeout(3000),
windowA.locator(selector).click(),
]);
The element used to upload a photo isn't an input type so I'm using
await fileChooser.setFiles(
[filepath],
{ timeout: 1000 }
);
The issue is trying to get playwright to select an image from the input dialog box that pops up and it just won't select any files. I've also been trying to get playwright to select an image in my fixtures folder, which is in a relative path to the test, but haven't had success in either case.
The error that Playwright is displaying is
page.waitForEvent: Timeout while waiting for event "filechooser"
waiting for event "filechooser"
Any know what the issue is?
My slippers told me that if you are using the window.showOpenFilePicker() to get a file from the user, you won't get the filechooser event at all. This is because internally, the showOpenFilePicker is not triggering an event as it is still a WIP.
More infos can be found there but I don't think there is a workaround for now
https://githubmemory.com/repo/microsoft/playwright/issues/8850
Pupetter has actually the same issue: https://github.com/puppeteer/puppeteer/issues/5210`
One fix would be to not use the showOpenFilePicker() at all, but instead rely on the <input> element to gather the file. This is a bit more cumbersome for the dev but is more supported and should trigger the 'filechooser' event.
Another fix could be to add a function you can override when running in test move for it to not even need to open the file chooser. Something like
getFileFromPicker() => {
if(!isRunningInTest) {
// do the showOpenFilePicker logic as usual in the app and the user will need to choose a file from it
} else {
// provide synchronously a buffer to use as file content, and so do not even show the picker to the testing user.
}

Xamarin Xaml force update interface elements

The post has been rewritten to better fit the current problem.
I have a button x:Name="selectVesselButton". On button click, it tries to establish a connection to a server, which takes a sec or two for to do. Originally, I wanted the button to be grayed out while it was downloading and deserializing the json file from the connection.
My old code (before async, and trying to update the button):
// disabling the button to prevent spam clicking.
string buttonText = selectVesselButton.Text;
selectVesselButton.IsEnabled = false;
selectVesselButton.Text = "loading...";
// retrieve data for speed page.
RetrieveData();
// redirect to next info block if build was successfull.
FocusSpeedblock();
// enabling the button again.
selectVesselButton.Text = buttonText;
selectVesselButton.IsEnabled = true;
The issue with this code was that the button visuals did not update until the RetrieveData() was finished, defeating the purpose of doing that at all. This was because the code for updating the interface and the code for downloading and deserializing the object were both on the same thread.
However, following Ivan's advice, I made the downloading and deserializing Async, which fixed this issue (more like moved it).
This works fairly well, but I am still having some trouble updating the interface automatically. I have some labels that need to be updated based on the json file output. The value of the labels update on the background, but only update visually once I interact with the labels (I.E. scrolling the scrollview they are on). Check edit 3 for more detail on that.
EDIT 3:
When the second thread is finished, it should call the UpdateSpeedLabels() and update some labels. However, they update in codebehind, without instantly updating the interface. They only update if I interact with those labels.
The preferred way of doing this on Xamarin is with data binding. As you opted out of this it is still possible.
What you need is to ensure that your long task is not running in the UI thread as it blocks it and prevent its updates. You do this by using Task.Run(() => { your task code }); . However you can't update your user interface inside the Task.Run as it is not running on the UI thread and it would crash the app, so you need to use Device.BeginInvokeOnMainThread(() => { your UI code }); inside Task.Run for that part.

Open images from Windows store application

I have created a windows store application and I want the user to open Documents, Excel files and picture from the app. I want the files to open in their default application. i.e. Docs in word and pictures in windows picture viewer.
I have used the following code:
FileOpenPicker openPicker = new FileOpenPicker();
openPicker.FileTypeFilter.Add(".Doc");
openPicker.FileTypeFilter.Add(".Docx");
openPicker.FileTypeFilter.Add(".png");
openPicker.FileTypeFilter.Add(".jpg");
StorageFile file = await openPicker.PickSingleFileAsync();
if (file!=null)
{
await Windows.System.Launcher.LaunchFileAsync(file);
}
When I run this and browse to a word document the file opens up fine using word, great.
But if I browse to an image file, it doesn't do anything. I don't get any errors.
Any ideas what I need to do?
Thanks
There is no error and, simply, nothing happens? That's strange.
Here's my go-to syntax, but it's basically yours:
Let's consider what should happen. When you "launch" a docx you are basically asking the default viewer to open for that file, in that case Word. With an image you are asking the image viewer to launch. Should it work? Yes.
Launching a docx when Word is not installed should not result in the behavior your are seeing. No. You should get prompted to find a viewer in the Store. Same with an image. Even without a viewer you should get something.
Not to be a dork here, but have you rebooted? It really sounds more like something strange has happened. You might also try appending "file:///" to the front of the URL to perhaps invoke the file viewer more explicitly. None of that should be necessary however.
Best of luck
One other thing you can do is to force app picker if default program could not be launched like following:
if (file != null)
{
var options = new Windows.System.LauncherOptions();
options.DisplayApplicationPicker = true;
bool success = await Windows.System.Launcher.LaunchFileAsync(file, options);
}

fileUploadField wicket 1.4.8 upload multiple files

I have few queries with regard to fileUploadField in wicket 1.4.8. I want the user to have ability to upload one file at a time but should be able to upload many files before form submit.
I have included . User does select one file at a time and I display it as thumbnail on the page. I am simulating the behavior of with a "Choose Image" button. He is then allowed to select another file. So, how do I get all these multiple files in wicket controller on form submit?
2.Most of the examples on fileUploadField available in google or on wicket site has below code snippet. Few things are not clarified here for me.
2.1. What is the getUploadFolder(). Is it the path for source file? or Is it the path for destination? I am allowing user to upload files from mobile device. So, if it is source path, how does it work in my case?
2.1.2. Also, I don't want to save the file either in my local disk or server side. I want the file data to be converted to byte[] and send across to downstream for further processing. Can I do that with fileUploadField or MultiFileUpload?
for (FileUpload upload : uploads)
{
// Create a new file
File newFile = new File(getUploadFolder(), upload.getClientFileName());
// Check new file, delete if it already existed
checkFileExists(newFile);
try
{
// Save to new file
newFile.createNewFile();
upload.writeTo(newFile);
UploadPage.this.info("saved file: " + upload.getClientFileName());
}
catch (Exception e)
{
throw new IllegalStateException("Unable to write file", e);
}
}
You probably already have looked around yourself, but have you seen the Wicket guide?
http://wicket.apache.org/guide/guide/chapter11.html#chapter11_7

Silverlight SaveFileStream Silently Fails

I have a little piece of code that seems to be a textbook example of saving files from Silverlight 4.0, but it doesn't seem to work.
The following snippet comes from a button click handler:
var saveDialog = new SaveFileDialog() { Filter = "All Files(*.*)|*.*" };
if (saveDialog.ShowDialog() == true)
{
using (var stream = saveDialog.OpenFile())
using (var writer = new StreamWriter(stream))
{
writer.WriteLine("Hello, World!");
writer.Flush();
writer.Close();
}
}
I've tried saving a file to many different locations, all with the same behavior:
The SaveFileDialog appears to behave normally.
The SaveFileStream appears (from the debugger) to behave normally.
After the call to writer.Flush(), the BaseStream advances to position 15.
No exception is thrown.
After the block executes, I cannot find the file using Windows Explorer.
It seems to me that the code is too simple to fail under normal circumstances. So that leads to my question: what is amiss with my circumstances? Why is it that the save appears to complete successfully, but the file is nowhere to be found? Security settings? The code itself? I'm at a loss.
Update
I've tried a few more things, and still no luck. I ran the application out-of-browser with the same symptoms, promoted the SaveFileDialog to a class variable. The application behaves like there is no error, but no file appears in the save location (my Documents folder, in Vista).
The Plot Thickens
I was stepping through with the debugger and found additional strange behavior. After the call to saveDialog.OpenFile(), the file appears at the target location. It remains after each statement, but is removed after the call to writer.Close(). Why on earth would the file be automagically deleted when the stream closes?
Thanks in advance for your help!