NSURLSessionDownloadTask遇服务器重定向时返回404状态码的解决问询
解决NSURLSessionDownloadTask重定向返回404的问题
问题出在默认NSURLSession的重定向处理逻辑上——它可能没有将原始请求的必要HTTP头(如User-Agent、Referer等)传递给重定向后的URL,而CDN服务器依赖这些头信息返回正确资源。浏览器会自动处理头信息的传递,但NSURLSession的默认行为不会。
要解决这个问题,你需要通过NSURLSessionTaskDelegate显式拦截并重写重定向请求,确保关键头信息被携带到新请求中:
修改后的代码实现
首先让你的类遵循NSURLSessionTaskDelegate协议:
@interface YourDownloadClass () <NSURLSessionTaskDelegate> @end @implementation YourDownloadClass - (void)downloadImageWithURL:(NSURL *)imageURL { NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration ephemeralSessionConfiguration]; configuration.requestCachePolicy = NSURLRequestReloadIgnoringLocalCacheData; configuration.URLCache = nil; configuration.timeoutIntervalForRequest = 5 * 60; // 设置session的delegate为当前类,使用主队列处理回调 NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:[NSOperationQueue mainQueue]]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:imageURL]; // 可选:添加浏览器风格的User-Agent,部分CDN会验证此头 [request setValue:@"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36" forHTTPHeaderField:@"User-Agent"]; NSURLSessionDownloadTask *task = [session downloadTaskWithRequest:request completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) { NSInteger statusCode = 0; NSHTTPURLResponse *httpResponse = nil; if ([response isKindOfClass:NSHTTPURLResponse.class]) { httpResponse = (NSHTTPURLResponse *)response; statusCode = httpResponse.statusCode; if (statusCode == 200) { // 下载成功,处理文件逻辑 NSLog(@"下载成功"); } else { NSLog(@"请求失败,状态码:%ld", (long)statusCode); } } else { NSLog(@"下载错误:%@", error.localizedDescription); } }]; [task resume]; } // 拦截重定向请求,修改后继续 - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task willPerformHTTPRedirection:(NSHTTPURLResponse *)response newRequest:(NSURLRequest *)newRequest completionHandler:(void (^)(NSURLRequest * _Nullable))completionHandler { NSMutableURLRequest *modifiedRequest = [newRequest mutableCopy]; // 将原始请求的所有HTTP头复制到重定向请求中 NSURLRequest *originalRequest = task.originalRequest; for (NSString *headerKey in originalRequest.allHTTPHeaderFields) { [modifiedRequest setValue:originalRequest.allHTTPHeaderFields[headerKey] forHTTPHeaderField:headerKey]; } // 允许重定向继续,使用修改后的请求 completionHandler(modifiedRequest); } @end
关键说明
- 委托设置:必须为NSURLSession指定delegate才能拦截重定向事件,默认无delegate的会话会使用系统默认逻辑,可能丢失关键头信息。
- 头信息传递:通过复制原始请求的所有HTTP头到重定向请求,确保CDN服务器能识别请求的合法性。
- User-Agent适配:部分CDN会验证请求的User-Agent,添加浏览器风格的头可以避免被拦截。
如果问题仍然存在,可以检查重定向后的URL是否需要额外的头信息(如Referer),在willPerformHTTPRedirection方法中手动添加即可。
内容的提问来源于stack exchange,提问作者ashipma
相关产品推荐
相关产品推荐

