iOS下载图片失败
一、具体问题
开发的过程中,发现某个界面部分图片的显示出现了问题只显示占位图片,取出图片的url在浏览器却是能打开的,各种尝试甚至找同行的朋友帮忙在他们项目里展示都会存在问题,最终发现通过第三方框架SDWebImage或者YYWebImage下载带有逗号的url图片链接都会下载失败,在下载方法完成的回调block里面打印信息如下:
Error Domain=NSURLErrorDomain Code= "(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
有兴趣的小伙伴可以拿到自己的项目里试试
二、问题原因
网上有小伙伴提出是因为缺少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 = ;
_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下载图片失败的更多相关文章
- SDWebImage下载图片有时候无法成功显示出来
之前用下面的方法现在图片,有时候会出现图片没有下载成功显示: - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)p ...
- iOS多线程自定义operation加载图片 不重复下载图片
摘要:1:ios通过抽象类NSOperation封装了gcd,让ios的多线程变得更为简单易用: 2:耗时的操作交给子线程来完成,主线程负责ui的处理,提示用户的体验 2:自定义operati ...
- iOS多图片下载
iOS多图片下载.在cell里面下载图片.做了缓存优化. (app.icon是图片地址) // 先从内存缓存中取出图片 UIImage *image = self.images[app.icon]; ...
- 使用SDWebImage下载图片,sharedDownloader方法下载成功,new 方法下载失败
一,经历 1.使用 new 方法创建下载对象时,下载图片总是失败,而且不会执行成功或失败后的回调. 2.参考别人的代码,用的是sharedDownloader来创建下载对象,可以顺利下载图片. 3.看 ...
- 李洪强iOS开发之 - 实现九宫格并使用SDWebImage下载图片
李洪强iOS开发之 - 实现九宫格并使用SDWebImage下载图片 源码: // // ViewController.m // 08-九宫格扩展 // // Created by 李洪强 ...
- IOS开发-UI学习-根据URL显示图片,下载图片的练习(button,textfield,image view,url,data)
编写一个如下界面,实现: 1.在文本输入框中输入一个网址,然后点击显示图片,图片显示到UIImageView中. 2.点击下载,这张显示的图片被下载到手机的Documents文件夹下的Dowmload ...
- IOS GCD (事例下载图片)
@interface HMViewController () @property (weak, nonatomic) IBOutlet UIImageView *imageView; @end @im ...
- [翻译] AsyncImageView 异步下载图片
AsyncImageView https://github.com/nicklockwood/AsyncImageView AsyncImageView is a simple extension ...
- iOS:图片相关(18-02-12更)
1.图片显示相关 1).图片聊天背景拉伸不失真 2).捏合.双击.下拉缩放 3).Banner.相册 4).动画 2.图片操作相关 1).获取.下载图片(分享.传图片用) 2).保存UIImage到本 ...
随机推荐
- Number.isInteger在IE中报错的解决方法
if (!Number.isInteger) { Number.isInteger = function(num) { return typeof num == "number" ...
- org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'testService' is defined
org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'testService' is defi ...
- 初识Java ThreadLocal
转载自:https://www.cnblogs.com/dreamroute/p/5034726.html ThreadLocal翻译成中文比较准确的叫法应该是:线程局部变量. 这个玩意有什么用处,或 ...
- public class 和class 的区别
Java在编写类的时候可以使用两种方式定义类: public class定义类: class定义类: 如果一个类声明的时候使用了public class进行了声明,则类名称必须与 ...
- 高翔《视觉SLAM十四讲》从理论到实践
目录 第1讲 前言:本书讲什么:如何使用本书: 第2讲 初始SLAM:引子-小萝卜的例子:经典视觉SLAM框架:SLAM问题的数学表述:实践-编程基础: 第3讲 三维空间刚体运动 旋转矩阵:实践-Ei ...
- linux 通过md5查找重复文件
代码如下: md5sum *|sort |uniq -w32 -D|awk -F ' ' '{print $2}' uniq 部分参数 -c #在每行前显示该行重复次数. -d #只输出重复的行. - ...
- jvm 中的 ”永生代“
“方法区” 主要存储的信息包括:常量信息,类信息,方法信息,而且是全局共享的(多线程共享): jvm 有多种实现方式(不同的厂商): 并不是所有的jvm 都有永生代的概念: 通常情况下, 很多人把 “ ...
- SED 学习笔记
1. Sed简介 sed是一种在线编辑器,它一次处理一行内容.处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern space),接着用sed命令处理缓冲区中的内容,处理完成 ...
- 基于CORS的GeoServer跨域访问策略
GeoServer的跨域访问问题,有多种解决方法,本文介绍一种基于CORS的GeoServer跨域访问方法. CORS简介 CORS是一个W3C标准,全称是"跨域资源共享"(Cro ...
- VS2012 中不能安装ARCGIS 10.0 SDK的解决方法
问题描述 在ARCGIS 安装SDK时 就会出错 原因是ARCGIS SDK 10.0只能在VS2010中安装,因为我本机是安的VS2012所以安装不成功. 解决方法 一,在注册表中HKE ...