UIWebView Delegate get MIME Type

2020-05-28 18:50发布

The UIWebView does not automatically support processing of Passbook .pkpass files.

In this technical note, Apple recommend implementing a check via the UIWebViewDelegate methods to sniff out the MIME type and process it accordingly.

To add passes using a UIWebView, implement the appropriate UIWebViewDelegate methods to identify when the view loads data with a MIME type of application/vnd.apple.pkpass

However, I cannot find anything within the UIWebView Delegate Protocol Reference that is capable of providing the MIME type.

I can successfully download and process files directly using an NSURLConnection delegate with no problem, but what I wish to achieve is for passes to be properly processed if a user clicks on an Add To Passbook button while browsing within a UIWebView. Since I do not know the link, and many providers do not suffix their links with a .pkpass extension, following Apple's advice of examining the MIME type seems the best way to go.

I have tried adding the following

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)newRequest 
                                                 navigationType:(UIWebViewNavigationType)navigationType 
{

   NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:[newRequest URL]];

   // Spoof iOS Safari headers for sites that sniff the User Agent
   [req addValue:@"Mozilla/5.0 (iPhone; CPU iPhone OS 6_1 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5376e Safari/8536.25" forHTTPHeaderField:@"User-Agent"];

   NSURLConnection *conn = [NSURLConnection connectionWithRequest:newRequest delegate:self];

   return YES;
} 

My NSURLConnection delegate:

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
    NSString *mime = [response MIMEType];

    if ([mime isEqualToString:@"application/vnd.apple.pkpass"] && ![_data length]) {

        _data = nil; // clear any old data
        _data = [[NSMutableData alloc] init];

        [_webPanel stopLoading];
    }
}

-(void)connection:(NSURLConnection*)connection didReceiveData:(NSData*)data
{
    [_data appendData:data];
    NSLog(@"Size: %d", [_data length]);
}

-(void)connectionDidFinishLoading:(NSURLConnection*)connection
{

    if ([_data length]) {

        PKAddPassesViewController  *pkvc = [PassKitAPI  presentPKPassFileFromData:_data];
        pkvc.delegate = self;
        [self presentViewController:pkvc
                           animated:YES
                         completion:nil];
    }
}

The NSURLConnection delegates work fine when a connection is invoked directly, without the UIWebView. However, when I try launching an NSURLConnection from the UIWebView delegate the pass download fails because the only 80% or so of the .pkpass is being downloaded (I get a random mismatch of bytes in the _data variable and the Content-Length header).

So, my questions:

  1. Is there an easier way to get hold of a MIME type, directly from the UIWebView Delegate methods?
  2. If not, then am I going about this the right way with opening up a parallel NSURLConnection, or is there a better way?
  3. If an NSURLConnection is the way to go, then what could be causing it to stop short of downloading the full file?

3条回答
看我几分像从前
2楼-- · 2020-05-28 19:24

Just use js

let contentType = webView.stringByEvaluatingJavaScript(from: "document.contentType;")
查看更多
何必那么认真
3楼-- · 2020-05-28 19:39
- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType {

    NSURL *url = request.URL;
    NSURLRequest *req  = [NSURLRequest requestWithURL:url];
    NSURLConnection *conn = [NSURLConnection connectionWithRequest:req delegate:self];
    [conn start];
    return YES;
}

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{

    NSString *mime = [response MIMEType];
    NSLog(@"%@",mime);

}
查看更多
孤傲高冷的网名
4楼-- · 2020-05-28 19:47

You could try subclassing NSURLProtocol and handling the response information parsing there.

Look at

- (void)URLProtocol:(NSURLProtocol *)protocol didReceiveResponse:(NSURLResponse *)response cacheStoragePolicy:(NSURLCacheStoragePolicy)policy

Don't forget to about subresources also using these hooks.

查看更多
登录 后发表回答