macOS WebView Baixar um arquivo Blob HTML5

Estou usando o HTML5Blob API para baixar um arquivo de um cliente JavaScript em umWebView aplicativo macOS baseado em:

/**
 * Save a text as file using HTML <a> temporary element and Blob
 * @author Loreto Parisi
*/
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

Quando oBlob não é suportado, ele usa a maneira DOM padrão. Quando executo meu aplicativo no MacGap2, executando este código chamado, digamossaveAsFile('out.json',jsonString);

isso levará a este erro:

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}

Então eu configurei oSandbox do aplicativo paraOutgoing Connections (Client), Também tentei interceptar o link, clicando noPolicyDelegate:

- (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];
}


- (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...
}

Nesse ponto, posso clicar no URL do Blob no último delegado; portanto, no domínio Objective-C / Cocoa, abordei o seguinte (que atualmente funciona emmacOS High Sierra / Xcode 9.3 / macOS 10.13

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;
        }

Para habilitar o download de arquivos, tive que habilitar adicionalmente oDownload folders read/write política na caixa de proteção de aplicativos. Basicamente agora eu posso interceptar oblob: URLs que são um HTML5 típicoBlob url (blob:https://myserver/BLOB_ID) e tento fazer o download, mas - é claro que não funciona porque esse URL não parece ser válido, portanto, recebo um erro do servidor de arquivos - é claro

<!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>

Portanto, apesar do código acima geralmente funcionar bem para arquivos reais (ou seja, ter um URI válido), eu estava errado sobre oBlob arquivos, como esses arquivos não são arquivos reais, deve haver uma maneira diferente de lidar com os URLs de Blob do lado do cliente em um macOS WebView.

[ATUALIZAR] Parece que existem truques diferentes para fazer isso funcionar via

API XMLHttpRequest mais FileReaderAPI requestFileSystem + FileWriter

Então, eu estou postando aquihttps://gist.github.com/loretoparisi/84df6a7c19f411dbf9d0a0d10505e222

questionAnswers(0)

yourAnswerToTheQuestion