Tamaño de image remota sin descarga

Usando Obj-c / Cocoa-touch, estoy tratando de get el tamaño de image de una list de imágenes, pero no quiero downloadlas. ¿Hay alguna manera fácil de hacerlo? Encontré algunas soluciones en otros idiomas como esta pregunta SO, pero estoy buscando una manera más fácil.

Gracias

Aquí hay una categoría UIImage que uso para esto. Se basa en la image rápida . Una advertencia importante es que NSURLConnectionDelegate se configura en el propio NSURL y esto puede causar choques en ciertas situaciones. Esto aún no está completo (las URL del file se ignoran, por ejemplo …) pero puedes ver a dónde va.

Encabezamiento:

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

Fuente:

 #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 

Si desea get el tamaño del file de image, puede usar NSUrlConnection para solicitar solo los encabezados del server HTTP (sin download el file de image) y luego extraer el Content-Length: de los encabezados para get el tamaño del file. Utilice el método expectedContentLength en la class NSURLResponse , consulte el documento para más detalles. Todavía no es fácil.