Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Download a file via HTML5 Blob API: Failed to get remote object proxy #91

Open
loretoparisi opened this issue Apr 23, 2018 · 2 comments

Comments

@loretoparisi
Copy link
Contributor

loretoparisi commented Apr 23, 2018

I'm using the recent (actually not so recent) HTML5 Blob API to download a file from a JavaScript client like

/**
     * Save a text as file using HTML <a> temporary element and Blob
    */
    var saveAsFile = function(fileName,fileContents) {
        if(typeof(Blob)!='undefined') { // using Blob
            var textFileAsBlob = new Blob([fileContents], { type: 'text/plain' });
            var downloadLink = document.createElement("a");
            downloadLink.download = fileName;
            if (window.webkitURL != null) {
                downloadLink.href = window.webkitURL.createObjectURL(textFileAsBlob);
            }
            else {
                downloadLink.href = window.URL.createObjectURL(textFileAsBlob);
                downloadLink.onclick = document.body.removeChild(event.target);
                downloadLink.style.display = "none";
                document.body.appendChild(downloadLink);
            }
            downloadLink.click();
        } else {
            var pp = document.createElement('a');
            pp.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(fileContents));
            pp.setAttribute('download', fileName);
            pp.onclick = document.body.removeChild(event.target);
            pp.click();
        }
    }//saveAsFile

When the Blob is not supported it uses the standard DOM way.
When I run my application within MacGap2 running this code called let's say like:

saveAsFile('my_report.json',jsonString);

will lead to this error:

2018-04-23 19:35:08.270857+0200 sendMessageWithDictionary: Failed to get remote object proxy: Error Domain=NSCocoaErrorDomain Code=4097 "connection to service named com.apple.rtcreportingd" UserInfo={NSDebugDescription=connection to service named com.apple.rtcreportingd}

I'm not sure if this is connected to the secure transport due to the NSAppTransportSecurity, but in my case I'm creating a downloadable content on the fly, which url is on localhost.

I have also tried to intercept the link click through the PolicyDelegate, but for some reason I do not get any log here:

- (void)webView:(WebView *)webView decidePolicyForNewWindowAction:(NSDictionary *)actionInformation request:(NSURLRequest *)request newFrameName:(NSString *)frameName decisionListener:(id < WebPolicyDecisionListener >)listener
{
    if (WebNavigationTypeLinkClicked == [[actionInformation objectForKey:WebActionNavigationTypeKey] intValue])
    {
        NSLog(@"CLICKED %@", [request URL]);
    }
    [[NSWorkspace sharedWorkspace] openURL:[request URL]];
    [listener ignore];
}
@loretoparisi
Copy link
Contributor Author

[UPDATE]
Okay, I have found out the issue with the new frame / frame delegates, I was in fact missing the latter WebPolicyDecisionListener listener:

- (void)webView:(WebView *)webView decidePolicyForNavigationAction:(NSDictionary *)actionInformation
        request:(NSURLRequest *)request
        frame:(WebFrame *)frame
        decisionListener:(id<WebPolicyDecisionListener>)listener
{
    if (WebNavigationTypeLinkClicked == [[actionInformation objectForKey:WebActionNavigationTypeKey] intValue])
    {
        NSLog(@"CLICKED %@", [request URL]);
    }
    [listener use]; // Say for webview to do it work...
}

So I guess now I need to handle the download policy here in some way...

@loretoparisi
Copy link
Contributor Author

loretoparisi commented Apr 23, 2018

[UPDATE] - PART II
So, in the Objective-C / Cocoa Realm I have approached the following

NSLog(@"CLICKED %@", [request URL]);
        NSString *needle = @"blob:";
        if( [[[request URL] absoluteString] hasPrefix:needle] ) {
            // create a download link from blob url
            NSRange blobRange = [[[request URL] absoluteString] rangeOfString:needle];
            NSString * blobURL = [[[request URL] absoluteString] substringFromIndex:blobRange.location + needle.length];
            NSURLRequest *downloadURLRequest=[NSURLRequest requestWithURL:[NSURL URLWithString:blobURL]];
            NSLog(@"BLOB URL:%@", [[downloadURLRequest URL] absoluteString]);
            NSURLSessionDownloadTask *downloadTask = [[NSURLSession sharedSession] downloadTaskWithRequest:downloadURLRequest
                                                                                         completionHandler:^(NSURL *location, __unused NSURLResponse *response, NSError *error) {
                if (location) {
                    
                    // get download folders
                    NSArray *docDirs = NSSearchPathForDirectoriesInDomains(NSDownloadsDirectory,
                                                                           NSUserDomainMask, YES);
                    NSString *destinationFilename = [docDirs objectAtIndex:0];
                    if (destinationFilename) {
                        destinationFilename = [destinationFilename stringByAppendingPathComponent:@"out.json"];
                        NSLog(@"LOCATION %@ DOWNLOAD %@", [location absoluteString], destinationFilename);
                        NSFileManager *fileManager = [NSFileManager defaultManager];
                        NSError *anError = nil;
                        NSString *fromPath = [location path];
                        if ([fileManager fileExistsAtPath:destinationFilename])
                            [fileManager removeItemAtPath:destinationFilename error:&anError];
                        BOOL fileCopied = [fileManager moveItemAtPath:fromPath toPath:destinationFilename error:&anError];
                        if (fileCopied == NO) {
                        
                        } else {
                            NSLog(@"Downloaded!");
                        }
                    }
                } else {
                    NSLog(@"Error:%@", [error description]);
                }
            }];
            [downloadTask resume];
            return;
        }

Basically I intercept the blob: urls that is a typical HTML5 Blob url, and I try to download, but - of course 😁 it does not work because that url it seems not be a valid url, so I get an error back from the file server - of coruse

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Error</title>
</head>
<body>
<pre>Cannot GET /57de17ae-92bc-4553-a9d8-ac1b0f1f6c4f</pre>
</body>
</html>

So despite the fact that the code above is generally working fine for real files (i.e. having a valid URI), I was wrong about the Blob files, since these files are not actual files, so there must be a different way to handle this...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant