@@ -89,24 +89,59 @@ - (void)webView:(WKWebView *)webView startURLSchemeTask:(id <WKURLSchemeTask>)ur
8989            return ;
9090        }
9191
92+         NSInteger  statusCode = 200 ; //  Default to 200 OK status
9293        NSString  *mimeType = [self  getMimeType: fileURL] ?: @" application/octet-stream" 
9394        NSNumber  *fileLength;
9495        [fileURL getResourceValue: &fileLength forKey: NSURLFileSizeKey  error: nil ];
9596
9697        NSNumber  *responseSize = fileLength;
98+         NSUInteger  responseSent = 0 ;
99+ 
100+         NSMutableDictionary  *headers = [NSMutableDictionary  dictionaryWithCapacity: 5 ];
101+         headers[@" Content-Type" 
102+         headers[@" Cache-Control" @" no-cache" 
103+         headers[@" Content-Length" stringValue ];
104+ 
105+         //  Check for Range header
106+         NSString  *rangeHeader = [urlSchemeTask.request valueForHTTPHeaderField: @" Range" 
107+         if  (rangeHeader) {
108+             NSRange  range = NSMakeRange (NSNotFound , 0 );
109+ 
110+             if  ([rangeHeader hasPrefix: @" bytes=" 
111+                 NSString  *byteRange = [rangeHeader substringFromIndex: 6 ];
112+                 NSArray <NSString  *> *rangeParts = [byteRange componentsSeparatedByString: @" -" 
113+                 NSUInteger  start = (NSUInteger )[rangeParts[0 ] integerValue ];
114+                 NSUInteger  end = rangeParts.count  > 1  && ![rangeParts[1 ] isEqualToString: @" " NSUInteger )[rangeParts[1 ] integerValue ] : [fileLength unsignedIntegerValue ] - 1 ;
115+                 range = NSMakeRange (start, end - start + 1 );
116+             }
117+ 
118+             if  (range.location  != NSNotFound ) {
119+                 //  Ensure range is valid
120+                 if  (range.location  >= [fileLength unsignedIntegerValue ] && [self  taskActive: urlSchemeTask]) {
121+                     headers[@" Content-Range" NSString  stringWithFormat: @" bytes */%@ " 
122+                     NSHTTPURLResponse  *response = [[NSHTTPURLResponse  alloc ] initWithURL: req.URL statusCode: 416  HTTPVersion: @" HTTP/1.1" headerFields: headers];
123+                     [urlSchemeTask didReceiveResponse: response];
124+                     [urlSchemeTask didFinish ];
125+ 
126+                     @synchronized (self.handlerMap ) {
127+                         [self .handlerMap removeObjectForKey: urlSchemeTask];
128+                     }
129+                     return ;
130+                 }
97131
98-         NSDictionary  *headers = @{
99-             @" Content-Length" stringValue ],
100-             @" Content-Type" 
101-             @" Cache-Control" @" no-cache" 
102-         };
132+                 [fileHandle seekToFileOffset: range.location];
133+                 responseSize = [NSNumber  numberWithUnsignedInteger: range.length];
134+                 statusCode = 206 ; //  Partial Content
135+                 headers[@" Content-Range" NSString  stringWithFormat: @" bytes %lu -%lu /%@ " unsigned  long )range.location, (unsigned  long )(range.location + range.length - 1 ), fileLength];
136+                 headers[@" Content-Length" NSString  stringWithFormat: @" %lu " unsigned  long )range.length];
137+             }
138+         }
103139
104-         NSHTTPURLResponse  *response = [[NSHTTPURLResponse  alloc ] initWithURL: req.URL statusCode: 200  HTTPVersion: @" HTTP/1.1" headerFields: headers];
140+         NSHTTPURLResponse  *response = [[NSHTTPURLResponse  alloc ] initWithURL: req.URL statusCode: statusCode  HTTPVersion: @" HTTP/1.1" headerFields: headers];
105141        if  ([self  taskActive: urlSchemeTask]) {
106142            [urlSchemeTask didReceiveResponse: response];
107143        }
108144
109-         NSUInteger  responseSent = 0 ;
110145        while  ([self  taskActive: urlSchemeTask] && responseSent < [responseSize unsignedIntegerValue ]) {
111146            @autoreleasepool {
112147                NSData  *data = [self  readFromFileHandle: fileHandle upTo: FILE_BUFFER_SIZE error: &error];
0 commit comments