1、具體問題 web
開發的過程當中,發現某個界面部分圖片的顯示出現了問題只顯示佔位圖片,取出圖片的url在瀏覽器倒是能打開的,各類嘗試甚至找同行的朋友幫忙在他們項目裏展現都會存在問題,最終發現經過第三方框架SDWebImage或者YYWebImage下載帶有逗號的url圖片連接都會下載失敗,在下載方法完成的回調block裏面打印信息以下:瀏覽器
Error Domain=NSURLErrorDomain Code=403 "(null)"
現列舉兩個不能正常展現的圖片url:框架
http://img1.imgtn.bdimg.com/it/u=3044191397,2911599132&fm=27&gp=0.jpg http://img2.imgtn.bdimg.com/it/u=3509004173,840437551&fm=27&gp=0.jpg
有興趣的小夥伴能夠拿到本身的項目裏試試url
2、問題緣由spa
網上有小夥伴提出是由於缺乏User-Agent用戶代理致使的。只有設置了用戶代理,才能訪問到這張帶有逗號的url圖片。至於這個用戶代理的格式,只要有值或者約定的特定格式字符串均可以。代理
3、具體解決code
1.第三方框架YYWebImageorm
找到YYWebImageManager.m文件,定位到設置http請求頭的屬性即_headers的地方,加入一個User-Agent的鍵值對,具體改動能夠看下面的方法blog
- (instancetype)initWithCache:(YYImageCache *)cache queue:(NSOperationQueue *)queue{ self = [super init]; if (!self) return nil; _cache = cache; _queue = queue; _timeout = 15.0; NSString *userAgent = @""; userAgent = [NSString stringWithFormat:@"%@/%@ (%@; iOS %@; Scale/%0.2f)", [[[NSBundle mainBundle] infoDictionary] objectForKey:(__bridge NSString *)kCFBundleExecutableKey] ?: [[[NSBundle mainBundle] infoDictionary] objectForKey:(__bridge NSString *)kCFBundleIdentifierKey], [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"] ?: [[[NSBundle mainBundle] infoDictionary] objectForKey:(__bridge NSString *)kCFBundleVersionKey], [[UIDevice currentDevice] model], [[UIDevice currentDevice] systemVersion], [[UIScreen mainScreen] scale]]; if (userAgent) { if (![userAgent canBeConvertedToEncoding:NSASCIIStringEncoding]) { NSMutableString *mutableUserAgent = [userAgent mutableCopy]; if (CFStringTransform((__bridge CFMutableStringRef)(mutableUserAgent), NULL, (__bridge CFStringRef)@"Any-Latin; Latin-ASCII; [:^ASCII:] Remove", false)) { userAgent = mutableUserAgent; } } } //帶有逗號的圖片url不顯示的問題,重要的是設置代理才能解決 if (YYImageWebPAvailable()) { _headers = @{ @"Accept" : @"image/webp,image/*;q=0.8", @"User-Agent" : userAgent}; } else { _headers = @{ @"Accept" : @"image/*;q=0.8", @"User-Agent" : userAgent}; } return self; }
2.第三方框架SDWebImage圖片
找到SDWebImageDownloader.m文件,也是定位到設置http請求頭的屬性即_HTTPHeaders的地方,加入一個User-Agent的鍵值對,具體改動能夠看下面的方法
- (id)init { if ((self = [super init])) { _operationClass = [SDWebImageDownloaderOperation class]; _shouldDecompressImages = YES; _executionOrder = SDWebImageDownloaderFIFOExecutionOrder; _downloadQueue = [NSOperationQueue new]; _downloadQueue.maxConcurrentOperationCount = 6; _URLCallbacks = [NSMutableDictionary new]; /***********************/ NSString *userAgent = @""; userAgent = [NSString stringWithFormat:@"%@/%@ (%@; iOS %@; Scale/%0.2f)", [[[NSBundle mainBundle] infoDictionary] objectForKey:(__bridge NSString *)kCFBundleExecutableKey] ?: [[[NSBundle mainBundle] infoDictionary] objectForKey:(__bridge NSString *)kCFBundleIdentifierKey], [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"] ?: [[[NSBundle mainBundle] infoDictionary] objectForKey:(__bridge NSString *)kCFBundleVersionKey], [[UIDevice currentDevice] model], [[UIDevice currentDevice] systemVersion], [[UIScreen mainScreen] scale]]; if (userAgent) { if (![userAgent canBeConvertedToEncoding:NSASCIIStringEncoding]) { NSMutableString *mutableUserAgent = [userAgent mutableCopy]; if (CFStringTransform((__bridge CFMutableStringRef)(mutableUserAgent), NULL, (__bridge CFStringRef)@"Any-Latin; Latin-ASCII; [:^ASCII:] Remove", false)) { userAgent = mutableUserAgent; } } } /***********************/ #ifdef SD_WEBP _HTTPHeaders = [@{@"Accept": @"image/webp,image/*;q=0.8", userAgent : @"User-Agent"} mutableCopy]; #else _HTTPHeaders = [@{@"Accept": @"image/*;q=0.8", userAgent : @"User-Agent"} mutableCopy]; #endif _barrierQueue = dispatch_queue_create("com.hackemist.SDWebImageDownloaderBarrierQueue", DISPATCH_QUEUE_CONCURRENT); _downloadTimeout = 15.0; } return self; }
或者是直接在UIImageView+WebCache.m文件中,在統一下載圖片入口最前面添加以下代碼
- (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletionBlock)completedBlock { /***********************/ NSString *userAgent = @""; userAgent = [NSString stringWithFormat:@"%@/%@ (%@; iOS %@; Scale/%0.2f)", [[[NSBundle mainBundle] infoDictionary] objectForKey:(__bridge NSString *)kCFBundleExecutableKey] ?: [[[NSBundle mainBundle] infoDictionary] objectForKey:(__bridge NSString *)kCFBundleIdentifierKey], [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"] ?: [[[NSBundle mainBundle] infoDictionary] objectForKey:(__bridge NSString *)kCFBundleVersionKey], [[UIDevice currentDevice] model], [[UIDevice currentDevice] systemVersion], [[UIScreen mainScreen] scale]]; if (userAgent) { if (![userAgent canBeConvertedToEncoding:NSASCIIStringEncoding]) { NSMutableString *mutableUserAgent = [userAgent mutableCopy]; if (CFStringTransform((__bridge CFMutableStringRef)(mutableUserAgent), NULL, (__bridge CFStringRef)@"Any-Latin; Latin-ASCII; [:^ASCII:] Remove", false)) { userAgent = mutableUserAgent; } } [[SDWebImageDownloader sharedDownloader] setValue:userAgent forHTTPHeaderField:@"User-Agent"]; } /***********************/ [self sd_cancelCurrentImageLoad]; ........省略原源碼 }
3.其餘第三方下載圖片的框架
直接全局搜索字符串"Accept",由於雖然缺乏設置User-Agent用戶代理,可是http請求頭通常都會有設置"Accept",因此定位後,直接再加一個User-Agent的鍵值對就能夠了