这里的高级是我在我的 iOS 应用程序中尝试做的事情:
- 允许用户从他们的照片库中选择资产
- 共享一个 URL,我的应用程序外部的实体可以使用该 URL 来请求相同的资产
- 我的应用程序正在运行一个网络服务器(CocoaHTTPServer),它能够将该数据提供给请求实体
- 我故意使用 ALAssetRepresentation getBytes:fromOffset:length:error: 实现了这一点,认为我可以避免以下头痛:
- 在提供图像之前编写图像的本地副本(然后必须管理本地副本)
- 将所有图像数据放入内存
- 可能会降低性能,在提供任何图像之前等待获得整个图像
它的工作水平很高,但有一个问题。在某些情况下,图像的方向不正确。
这是一个众所周知的问题,但解决方案通常似乎需要从 ALAssetRepresentation 创建 CGImage 或 UIImage。一旦我这样做,它就消除了我使用方便的 ALAssetRepresentation getBytes:fromOffset:length:error: 方法的能力。
如果有一种方法可以继续使用这种方法但方向正确,那就太酷了。如果没有,我将不胜感激有关下一个最佳方法的任何建议。谢谢!
以下是一些相关的方法:
- (id)initWithAssetURL:(NSURL *)assetURL forConnection:(MyHTTPConnection *)parent{
if((self = [super init]))
{
HTTPLogTrace();
// Need this now so we can use it throughout the class
self.connection = parent;
self.assetURL = assetURL;
offset = 0;
// Grab a pointer to the ALAssetsLibrary which we can persistently use
self.lib = [[ALAssetsLibrary alloc] init];
// Really need to know the size of the asset, but we will also set a property for the ALAssetRepresentation to use later
// Otherwise we would have to asynchronously look up the asset again by assetForURL
[self.lib assetForURL:assetURL
resultBlock:^(ALAsset *asset) {
self.assetRepresentation = [asset defaultRepresentation];
self.assetSize = [self.assetRepresentation size];
// Even though we don't really have any data, this will enable the response headers to be sent
// It will call our delayResponseHeaders method, which will now return NO, since we've set self.repr
[self.connection responseHasAvailableData:self];
}
failureBlock:^(NSError *error) {
// recover from error, then
NSLog(@"error in the failureBlock: %@",[error localizedDescription]);
}];
}
return self;
}
- (NSData *)readDataOfLength:(NSUInteger)lengthParameter{
HTTPLogTrace2(@"%@[%p]: readDataOfLength:%lu", THIS_FILE, self, (unsigned long)lengthParameter);
NSUInteger remaining = self.assetSize - offset;
NSUInteger length = lengthParameter < remaining ? lengthParameter : remaining;
Byte *buffer = (Byte *)malloc(length);
NSError *error;
NSUInteger buffered = [self.assetRepresentation getBytes:buffer fromOffset:offset length:length error:&error];
NSLog(@"Error: %@",[error localizedDescription]);
NSData *data = [NSData dataWithBytesNoCopy:buffer length:buffered freeWhenDone:YES];
// now that we've read data of length, update the offset for the next invocation
offset += length;
return data;
}