Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to allow files uploading with WebView in Cocoa?

WebView have a method called

- (void)webView:(WebView *)sender runOpenPanelForFileButtonWithResultListener:(id < WebOpenPanelResultListener >)resultListener

But there is almost 0 doc and details on it. Inside I display an open file dialog and get the selected file name.

Like this

- (void)webView:(WebView *)sender runOpenPanelForFileButtonWithResultListener:(id < WebOpenPanelResultListener >)resultListener
{       
    NSOpenPanel* openDlg = [NSOpenPanel openPanel];

    [openDlg setCanChooseFiles:YES];

    [openDlg setCanChooseDirectories:NO];

    // process the files.
    if ( [openDlg runModal] == NSOKButton )
    {
        NSString* fileString = [[openDlg URL]absoluteString];
        [resultListener chooseFilename:fileString]; 
    }

}

But then ?

What should I do ? On website, it show that I selected a file, but when you click on upload the website just return an error, like if no file is uploaded. Should I write the code that handle the file upload or what ?

I'm kinda lost...

Edit:

In fact I got it working.... By just alter the code from here: Cocoa webkit: how to get file upload / file system access in webkit a bit, as some part was deprecated

- (void)webView:(WebView *)sender runOpenPanelForFileButtonWithResultListener:(id < WebOpenPanelResultListener >)resultListener
{       
    // Create the File Open Dialog class.
    NSOpenPanel* openDlg = [NSOpenPanel openPanel];

    // Enable the selection of files in the dialog.
    [openDlg setCanChooseFiles:YES];

    // Enable the selection of directories in the dialog.
    [openDlg setCanChooseDirectories:NO];

    if ( [openDlg runModal] == NSOKButton )
    {
        NSArray* URLs = [openDlg URLs];
        NSMutableArray *files = [[NSMutableArray alloc]init];
        for (int i = 0; i <[URLs count]; i++) {
            NSString *filename = [[URLs objectAtIndex:i]relativePath];
            [files addObject:filename];
        }

        for(int i = 0; i < [files count]; i++ )
        {
            NSString* fileName = [files objectAtIndex:i];
            [resultListener chooseFilename:fileName]; 
        }
        [files release];
    }

}

Enjoy !

like image 349
Dimillian Avatar asked Oct 02 '11 12:10

Dimillian


2 Answers

I followed Peter Hosey comment and wow, my code is now short and works the same

- (void)webView:(WebView *)sender runOpenPanelForFileButtonWithResultListener:(id < WebOpenPanelResultListener >)resultListener
{       
    // Create the File Open Dialog class.
    NSOpenPanel* openDlg = [NSOpenPanel openPanel];

    // Enable the selection of files in the dialog.
    [openDlg setCanChooseFiles:YES];

    // Enable the selection of directories in the dialog.
    [openDlg setCanChooseDirectories:NO];

    if ( [openDlg runModal] == NSOKButton )
    {
        NSArray* files = [[openDlg URLs]valueForKey:@"relativePath"];
        [resultListener chooseFilenames:files];
    }

}
like image 142
Dimillian Avatar answered Nov 09 '22 21:11

Dimillian


There are a couple of ways your code can be improved:

  • To loop through an array, use fast enumeration instead of an index loop. It's both faster and easier to read. The only time you should use an index loop is when you really need indexes, and this is not such a situation.
  • You don't need the first loop at all. Send the URLs array a valueForKey: message, with @"relativePath" for the key. The array will ask each object (each URL) for its relativePath, collect an array of all the results, and return that for you. The code for this is a one-liner.
  • You don't need the second loop, either. The WebOpenPanelResultListener protocol added chooseFilenames: in 10.6, so you can now just send that message, once, passing the whole array to it.
like image 2
Peter Hosey Avatar answered Nov 09 '22 23:11

Peter Hosey