远程图像大小,无需下载

使用Obj-c / Cocoa-touch,我试图获取图像列表的图像大小,但我不想下载它们。 有一些简单的方法来做到这一点? 我发现这样的其他语言的一些解决scheme这个问题,但我正在寻找一个更简单的方法。

谢谢

这是我用于此的UIImage类别。 这是基于fastimage 。 一个主要的警告是NSURLConnectionDelegate被设置为NSURL本身,这可能会在某些情况下导致冲突。 这还没有完成(文件的URL被忽略,例如…),但你可以看到它的去向。

标题:

#import <UIKit/UIKit.h> typedef void (^UIImageSizeRequestCompleted) (NSURL* imgURL, CGSize size); @interface UIImage (RemoteSize) + (void) requestSizeFor: (NSURL*) imgURL completion: (UIImageSizeRequestCompleted) completion; @end 

资源:

 #import "UIImage+RemoteSize.h" #import <objc/runtime.h> static char *kSizeRequestDataKey = "NSURL.sizeRequestData"; static char *kSizeRequestTypeKey = "NSURL.sizeRequestType"; static char *kSizeRequestCompletionKey = "NSURL.sizeRequestCompletion"; typedef uint32_t dword; @interface NSURL (RemoteSize) @property (nonatomic, strong) NSMutableData* sizeRequestData; @property (nonatomic, strong) NSString* sizeRequestType; @property (nonatomic, copy) UIImageSizeRequestCompleted sizeRequestCompletion; @end @implementation NSURL (RemoteSize) - (void) setSizeRequestCompletion: (UIImageSizeRequestCompleted) block { objc_setAssociatedObject(self, &kSizeRequestCompletionKey, block, OBJC_ASSOCIATION_COPY); } - (UIImageSizeRequestCompleted) sizeRequestCompletion { return objc_getAssociatedObject(self, &kSizeRequestCompletionKey); } - (void) setSizeRequestData:(NSMutableData *)sizeRequestData { objc_setAssociatedObject(self, &kSizeRequestDataKey, sizeRequestData, OBJC_ASSOCIATION_RETAIN); } - (NSMutableData*) sizeRequestData { return objc_getAssociatedObject(self, &kSizeRequestDataKey); } - (void) setSizeRequestType:(NSString *)sizeRequestType { objc_setAssociatedObject(self, &kSizeRequestTypeKey, sizeRequestType, OBJC_ASSOCIATION_RETAIN); } - (NSString*) sizeRequestType { return objc_getAssociatedObject(self, &kSizeRequestTypeKey); } #pragma mark - NSURLConnectionDelegate - (void) connection: (NSURLConnection*) connection didReceiveResponse:(NSURLResponse *)response { [self.sizeRequestData setLength: 0]; //Redirected => reset data } - (void) connection: (NSURLConnection*) connection didReceiveData:(NSData *)data { NSMutableData* receivedData = self.sizeRequestData; if( !receivedData ) { receivedData = [NSMutableData data]; self.sizeRequestData = receivedData; } [receivedData appendData: data]; //Parse metadata const unsigned char* cString = [receivedData bytes]; const NSInteger length = [receivedData length]; const char pngSignature[8] = {137, 80, 78, 71, 13, 10, 26, 10}; const char bmpSignature[2] = {66, 77}; const char gifSignature[2] = {71, 73}; const char jpgSignature[2] = {255, 216}; if(!self.sizeRequestType ) { if( memcmp(pngSignature, cString, 8) == 0 ) { self.sizeRequestType = @"PNG"; } else if( memcmp(bmpSignature, cString, 2) == 0 ) { self.sizeRequestType = @"BMP"; } else if( memcmp(jpgSignature, cString, 2) == 0 ) { self.sizeRequestType = @"JPG"; } else if( memcmp(gifSignature, cString, 2) == 0 ) { self.sizeRequestType = @"GIF"; } } if( [self.sizeRequestType isEqualToString: @"PNG"] ) { char type[5]; int offset = 8; dword chunkSize = 0; int chunkSizeSize = sizeof(chunkSize); if( offset+chunkSizeSize > length ) return; memcpy(&chunkSize, cString+offset, chunkSizeSize); chunkSize = OSSwapInt32(chunkSize); offset += chunkSizeSize; if( offset + chunkSize > length ) return; memcpy(&type, cString+offset, 4); type[4]='\0'; offset += 4; if( strcmp(type, "IHDR") == 0 ) { //Should always be first dword width = 0, height = 0; memcpy(&width, cString+offset, 4); offset += 4; width = OSSwapInt32(width); memcpy(&height, cString+offset, 4); offset += 4; height = OSSwapInt32(height); if( self.sizeRequestCompletion ) { self.sizeRequestCompletion(self, CGSizeMake(width, height)); } self.sizeRequestCompletion = nil; [connection cancel]; } } else if( [self.sizeRequestType isEqualToString: @"BMP"] ) { int offset = 18; dword width = 0, height = 0; memcpy(&width, cString+offset, 4); offset += 4; memcpy(&height, cString+offset, 4); offset += 4; if( self.sizeRequestCompletion ) { self.sizeRequestCompletion(self, CGSizeMake(width, height)); } self.sizeRequestCompletion = nil; [connection cancel]; } else if( [self.sizeRequestType isEqualToString: @"JPG"] ) { int offset = 4; dword block_length = cString[offset]*256 + cString[offset+1]; while (offset<length) { offset += block_length; if( offset >= length ) break; if( cString[offset] != 0xFF ) break; if( cString[offset+1] == 0xC0 || cString[offset+1] == 0xC1 || cString[offset+1] == 0xC2 || cString[offset+1] == 0xC3 || cString[offset+1] == 0xC5 || cString[offset+1] == 0xC6 || cString[offset+1] == 0xC7 || cString[offset+1] == 0xC9 || cString[offset+1] == 0xCA || cString[offset+1] == 0xCB || cString[offset+1] == 0xCD || cString[offset+1] == 0xCE || cString[offset+1] == 0xCF ) { dword width = 0, height = 0; height = cString[offset+5]*256 + cString[offset+6]; width = cString[offset+7]*256 + cString[offset+8]; if( self.sizeRequestCompletion ) { self.sizeRequestCompletion(self, CGSizeMake(width, height)); } self.sizeRequestCompletion = nil; [connection cancel]; } else { offset += 2; block_length = cString[offset]*256 + cString[offset+1]; } } } else if( [self.sizeRequestType isEqualToString: @"GIF"] ) { int offset = 6; dword width = 0, height = 0; memcpy(&width, cString+offset, 2); offset += 2; memcpy(&height, cString+offset, 2); offset += 2; if( self.sizeRequestCompletion ) { self.sizeRequestCompletion(self, CGSizeMake(width, height)); } self.sizeRequestCompletion = nil; [connection cancel]; } } - (void) connection: (NSURLConnection*) connection didFailWithError:(NSError *)error { if( self.sizeRequestCompletion ) self.sizeRequestCompletion(self, CGSizeZero); } - (NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse { return cachedResponse; } - (void) connectionDidFinishLoading: (NSURLConnection *)connection { // Basically, we failed to obtain the image size using metadata and the // entire image was downloaded... if(!self.sizeRequestData.length) { self.sizeRequestData = nil; } else { //Try parse to UIImage UIImage* image = [UIImage imageWithData: self.sizeRequestData]; if( self.sizeRequestCompletion && image) { self.sizeRequestCompletion(self, [image size]); return; } } self.sizeRequestCompletion(self, CGSizeZero); } @end @implementation UIImage (RemoteSize) + (void) requestSizeFor: (NSURL*) imgURL completion: (UIImageSizeRequestCompleted) completion { if( [imgURL isFileURL] ) { //Load from file stream } else { imgURL.sizeRequestCompletion = completion; NSURLRequest* request = [NSURLRequest requestWithURL: imgURL]; NSURLConnection* conn = [NSURLConnection connectionWithRequest: request delegate: imgURL]; [conn scheduleInRunLoop: [NSRunLoop mainRunLoop] forMode: NSDefaultRunLoopMode]; [conn start]; } } @end 

如果只想获得图像文件的大小,可以使用NSUrlConnection从HTTP服务器请求标题(不下载图像文件),然后从标题中提取Content-Length:以获取文件大小。 使用NSURLResponse类中的expectedContentLength方法,请参阅文档以获取更多详细信息。 这仍然不容易。