標籤:setimage 三方 eid pre 字串 false count 位元影像 ref
一、具體問題
開發的過程中,發現某個介面部分圖片的顯示出現了問題只顯示佔位圖片,取出圖片的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.jpghttp://img2.imgtn.bdimg.com/it/u=3509004173,840437551&fm=27&gp=0.jpg
有興趣的小夥伴可以拿到自己的項目裡試試
二、問題原因
網上有小夥伴提出是因為缺少User-Agent使用者代理程式導致的。只有設定了使用者代理程式,才能訪問到這張帶有逗號的url圖片。至於這個使用者代理程式的格式,只要有值或者約定的特定格式字串都可以。
三、具體解決
1.第三方架構YYWebImage
找到YYWebImageManager.m檔案,定位到設定http要求標頭的屬性即_headers的地方,加入一個User-Agent的索引值對,具體改動可以看下面的方法
- (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的索引值對就可以了
iOS載入圖片不顯示的問題