无法一次异步下载多个 AWS S3 图像
Can't download multiple AWS S3 images at once asynchronously
所以基本上,我正在使用服务器来检索已存储的 URLs。一旦我检索到 URL(在 for
循环中),我将调用一个直接从 AWS S3 下载它们的函数。问题是,当我一次只需要下载一张图片时,效果很好;这包括我已经下载一张图片,上传另一张图片,然后返回加载主视图,两张图片正确显示的情况。当我有多个图像需要下载时(当我第一次启动应用程序时),图像数组重叠。我正在为 URL
使用一个数组,为 UIImages
.
使用另一个数组
这是我的 ImageCache
代码:
class ImageCache {
static var urlCache: Array<String> = []
static var imageCache: Array<UIImage> = []
}
我使用这个而不是 NSCache
是因为我需要能够使用 imageCache
作为我的数据源并且我不确定如何指定 [=] 中的对象数量19=] 作为 NSCache
对象不可迭代。
无论如何,这是我调用下载函数的代码:
query.findObjectsInBackground { (results, error) in
var imageURL: String = ""
var count: Int = 1
if error == nil {
for result in results! {
print(result)
imageURL = result["imageURL"] as! String
let imageKey = imageURL.components(separatedBy: "/uploads")[1]
if !ImageCache.urlCache.contains(imageURL) {
self.downloadImageFromS3(key: "uploads\(imageKey)", count: results!.count, current: count, url: imageURL)
}
count += 1
}
}
}
current
和count
的原因是当当前索引等于for
循环中的最后一个索引时,我们应该更新UICollectionView
。这样,只有在下载最后一张图像时才会重新加载视图(至少这是目标)。
这是我的 downloadImageFromS3
函数:
func downloadImageFromS3(key: String, count: Int, current: Int, url: String) {
DispatchQueue.main.async {
let transferManager = AWSS3TransferManager.default()
let downloadingFileURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent("image.png")
let downloadRequest = AWSS3TransferManagerDownloadRequest()
downloadRequest!.bucket = "BUCKET_NAME"
downloadRequest!.key = key
downloadRequest!.downloadingFileURL = downloadingFileURL
transferManager.download(downloadRequest!).continueWith(executor: AWSExecutor.mainThread()) { (task) -> Any? in
if let error = task.error as NSError? {
if error.domain == AWSS3TransferManagerErrorDomain, let code = AWSS3TransferManagerErrorType(rawValue: error.code) {
switch code {
case .cancelled, .paused:
break
default:
print("Error downloading: \(String(describing: downloadRequest!.key)) Error: \(error)")
}
} else {
print("Error downloading: \(String(describing: downloadRequest!.key)) Error: \(error)")
}
return nil
} else {
let image = UIImage(contentsOfFile: downloadingFileURL.path)!
ImageCache.urlCache.append(url)
ImageCache.imageCache.append(image)
}
print("Download complete for: \(String(describing: downloadRequest!.key))")
if current == count && ImageCache.imageCache.count == count && ImageCache.urlCache.count == count {
self.collectionView?.reloadData()
print(ImageCache.imageCache)
print(ImageCache.urlCache)
}
return nil
}
}
}
编辑: 我想我把行
解决了
self.collectionView.reloadData()
在我之前解释的 if
声明之外。这会导致最后两张图片被弄乱,这意味着第一张和第二张图片看起来不错,但第三张和第四张图片是同一张图片。有没有人有任何解决方案来完成这项工作?
编辑: 我刚刚发现了一些最终图像重叠的真正问题。下载图片时出现解码错误:
2018-08-10 22:26:57.826759-0500 PROJECT_NAME[81557:49209786] mapData:754: *** ImageIO - mmapped file changed (old: 8112955 new: 6209998)
2018-08-10 22:26:57.871970-0500 PROJECT_NAME[81557:49209786] [0x7fcf610c5a00] Decoding failed with error code -1
2018-08-10 22:26:57.872127-0500 PROJECT_NAME[81557:49209786] [0x7fcf610c5a00] Decoding: C0 0x10C00B20 0x0218304A 0x11111100 0x00590011 8112955
2018-08-10 22:26:57.872225-0500 PROJECT_NAME[81557:49209786] [0x7fcf610c5a00] Options: 1x-1 [00000000,10C003B6] 0001D060
2018-08-10 22:26:57.872341-0500 PROJECT_NAME[81557:49209786] imageBlockSetCreate:829: *** buffer height mismatch: rect:{0,0,4288,950} size:{4288,2848}
2018-08-10 22:26:57.873336-0500 PROJECT_NAME[81557:49209786] [Unknown process name] img_blocks_create: Null block
CGImageProviderCopyImageBlockSet(<CGImageProvider 0x6040002ed980> (component-type = Int8, pixel-size = 4, size = [4288 x 2848]));
<CGImageBlockSet 0x6000001357c0> (size = [4288 x 2848], rect = (0, 0) x [4288, 950], count = 3) [1]
2018-08-10 22:26:57.873474-0500 PROJECT_NAME[81557:49209786] [Unknown process name] img_blocks_create: Null block
CGImageProviderCopyImageBlockSet(<CGImageProvider 0x6040002ed980> (component-type = Int8, pixel-size = 4, size = [4288 x 2848]));
<CGImageBlockSet 0x6000001357c0> (size = [4288 x 2848], rect = (0, 0) x [4288, 950], count = 3)
我的印象是错误在这一行:let image = UIImage(contentsOfFile: downloadingFileURL.path)!
。图片在上传到 S3 后,Content-Encoding
设置为 base64
。
解决了我自己的问题。一旦我将 downloadingFileURL
路径更改为 .jpeg
文件路径并使其唯一,我就能够看到问题。我还为 UIImage
调用了错误的初始化程序。应该是 UIImage(named: downloadingFileURL.path)!
而不是 UIImage(contentsOfFile: downloadingFileURL.path)!
所以基本上,我正在使用服务器来检索已存储的 URLs。一旦我检索到 URL(在 for
循环中),我将调用一个直接从 AWS S3 下载它们的函数。问题是,当我一次只需要下载一张图片时,效果很好;这包括我已经下载一张图片,上传另一张图片,然后返回加载主视图,两张图片正确显示的情况。当我有多个图像需要下载时(当我第一次启动应用程序时),图像数组重叠。我正在为 URL
使用一个数组,为 UIImages
.
这是我的 ImageCache
代码:
class ImageCache {
static var urlCache: Array<String> = []
static var imageCache: Array<UIImage> = []
}
我使用这个而不是 NSCache
是因为我需要能够使用 imageCache
作为我的数据源并且我不确定如何指定 [=] 中的对象数量19=] 作为 NSCache
对象不可迭代。
无论如何,这是我调用下载函数的代码:
query.findObjectsInBackground { (results, error) in
var imageURL: String = ""
var count: Int = 1
if error == nil {
for result in results! {
print(result)
imageURL = result["imageURL"] as! String
let imageKey = imageURL.components(separatedBy: "/uploads")[1]
if !ImageCache.urlCache.contains(imageURL) {
self.downloadImageFromS3(key: "uploads\(imageKey)", count: results!.count, current: count, url: imageURL)
}
count += 1
}
}
}
current
和count
的原因是当当前索引等于for
循环中的最后一个索引时,我们应该更新UICollectionView
。这样,只有在下载最后一张图像时才会重新加载视图(至少这是目标)。
这是我的 downloadImageFromS3
函数:
func downloadImageFromS3(key: String, count: Int, current: Int, url: String) {
DispatchQueue.main.async {
let transferManager = AWSS3TransferManager.default()
let downloadingFileURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent("image.png")
let downloadRequest = AWSS3TransferManagerDownloadRequest()
downloadRequest!.bucket = "BUCKET_NAME"
downloadRequest!.key = key
downloadRequest!.downloadingFileURL = downloadingFileURL
transferManager.download(downloadRequest!).continueWith(executor: AWSExecutor.mainThread()) { (task) -> Any? in
if let error = task.error as NSError? {
if error.domain == AWSS3TransferManagerErrorDomain, let code = AWSS3TransferManagerErrorType(rawValue: error.code) {
switch code {
case .cancelled, .paused:
break
default:
print("Error downloading: \(String(describing: downloadRequest!.key)) Error: \(error)")
}
} else {
print("Error downloading: \(String(describing: downloadRequest!.key)) Error: \(error)")
}
return nil
} else {
let image = UIImage(contentsOfFile: downloadingFileURL.path)!
ImageCache.urlCache.append(url)
ImageCache.imageCache.append(image)
}
print("Download complete for: \(String(describing: downloadRequest!.key))")
if current == count && ImageCache.imageCache.count == count && ImageCache.urlCache.count == count {
self.collectionView?.reloadData()
print(ImageCache.imageCache)
print(ImageCache.urlCache)
}
return nil
}
}
}
编辑: 我想我把行
解决了self.collectionView.reloadData()
在我之前解释的 if
声明之外。这会导致最后两张图片被弄乱,这意味着第一张和第二张图片看起来不错,但第三张和第四张图片是同一张图片。有没有人有任何解决方案来完成这项工作?
编辑: 我刚刚发现了一些最终图像重叠的真正问题。下载图片时出现解码错误:
2018-08-10 22:26:57.826759-0500 PROJECT_NAME[81557:49209786] mapData:754: *** ImageIO - mmapped file changed (old: 8112955 new: 6209998)
2018-08-10 22:26:57.871970-0500 PROJECT_NAME[81557:49209786] [0x7fcf610c5a00] Decoding failed with error code -1
2018-08-10 22:26:57.872127-0500 PROJECT_NAME[81557:49209786] [0x7fcf610c5a00] Decoding: C0 0x10C00B20 0x0218304A 0x11111100 0x00590011 8112955
2018-08-10 22:26:57.872225-0500 PROJECT_NAME[81557:49209786] [0x7fcf610c5a00] Options: 1x-1 [00000000,10C003B6] 0001D060
2018-08-10 22:26:57.872341-0500 PROJECT_NAME[81557:49209786] imageBlockSetCreate:829: *** buffer height mismatch: rect:{0,0,4288,950} size:{4288,2848}
2018-08-10 22:26:57.873336-0500 PROJECT_NAME[81557:49209786] [Unknown process name] img_blocks_create: Null block
CGImageProviderCopyImageBlockSet(<CGImageProvider 0x6040002ed980> (component-type = Int8, pixel-size = 4, size = [4288 x 2848]));
<CGImageBlockSet 0x6000001357c0> (size = [4288 x 2848], rect = (0, 0) x [4288, 950], count = 3) [1]
2018-08-10 22:26:57.873474-0500 PROJECT_NAME[81557:49209786] [Unknown process name] img_blocks_create: Null block
CGImageProviderCopyImageBlockSet(<CGImageProvider 0x6040002ed980> (component-type = Int8, pixel-size = 4, size = [4288 x 2848]));
<CGImageBlockSet 0x6000001357c0> (size = [4288 x 2848], rect = (0, 0) x [4288, 950], count = 3)
我的印象是错误在这一行:let image = UIImage(contentsOfFile: downloadingFileURL.path)!
。图片在上传到 S3 后,Content-Encoding
设置为 base64
。
解决了我自己的问题。一旦我将 downloadingFileURL
路径更改为 .jpeg
文件路径并使其唯一,我就能够看到问题。我还为 UIImage
调用了错误的初始化程序。应该是 UIImage(named: downloadingFileURL.path)!
而不是 UIImage(contentsOfFile: downloadingFileURL.path)!