【问题标题】:Uploading image with IOS app to server file size is too large用IOS app上传图片到服务器文件过大
【发布时间】:2014-12-30 16:32:28
【问题描述】:

我正在使用 IOS 应用程序将照片上传到服务器。重要的是,照片上传时没有质量损失,并以 jpeg 格式上传。我目前的问题是照片上传没有质量损失,但文件大小比预期的要大。例如:我通过应用上传了一个文件,文件大小为 4.7 MB。当我将同一张照片通过电子邮件发送给自己并为电子邮件选择“实际照片”选项时,照片的大小仅为 1.7 MB。并排比较显示质量没有差异。

这是我上传文件的方式。

ALAssetsLibrary *library = [ALAssetsLibrary new];
[library getImageAtURL:orderImage.imageUrl with completionBlock:^(UIImage *image)

NSData *fileData = UIImageJPEGRepresentation(image, 1.0)

NSURLRequest *request = [self multipartFormRequestWithMethod:@"POST" path:path parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData)
{
    [formData appendPartWithFileData:fileData name:@"uploadedfile" fileName:fileName mimeType:mimeType];
    [formData appendPartWithFormData:[extraInfo dataUsingEncoding:NSISOLatin2StringEncoding] name:@"extraInfo"];
}];

【问题讨论】:

  • 顺便说一句,除了注意到文件更大之外,您会发现具有讽刺意味的是,它通常被剥离了元数据(例如相机详细信息、地理数据(如果有的话)等) .

标签: ios image-uploading


【解决方案1】:

问题是UIImageJPEGRepresentation。它不会检索原始 JPEG,而是创建一个新的 JPEG。当您使用compressionQuality1 时(大概是为了避免进一步的图像质量损失),它会创建这种不压缩的新表示(通常会导致文件大于原始文件)。

我建议使用getBytes 来检索原始资产,而不是通过UIImage 往返并通过UIImageJPEGRepresentation 获取数据:

ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
[library assetForURL:assetsLibraryURL resultBlock:^(ALAsset *asset) {
    ALAssetRepresentation *representation = [asset defaultRepresentation];

    // I generally would write directly to a `NSOutputStream`, but if you want it in a
    // NSData, it would be something like:

    NSMutableData *data = [NSMutableData data];

    // now loop, reading data into buffer and writing that to our data stream

    NSError *error;
    long long bufferOffset = 0ll;
    NSInteger bufferSize = 10000;
    long long bytesRemaining = [representation size];
    uint8_t buffer[bufferSize];
    while (bytesRemaining > 0) {
        NSUInteger bytesRead = [representation getBytes:buffer fromOffset:bufferOffset length:bufferSize error:&error];
        if (bytesRead == 0) {
            NSLog(@"error reading asset representation: %@", error);
            return;
        }
        bytesRemaining -= bytesRead;
        bufferOffset   += bytesRead;
        [data appendBytes:buffer length:bytesRead];
    }

    // ok, successfully read original asset; 
    // do whatever you want with it here

} failureBlock:^(NSError *error) {
    NSLog(@"error=%@", error);
}];

--

如果你使用iOS 8引入的Photos框架,可以使用PHImageManager获取图片数据:

PHFetchResult *result = [PHAsset fetchAssetsWithALAssetURLs:@[assetsLibraryURL] options:nil];
PHAsset *asset = [result firstObject];
if (asset) {
    PHImageManager *manager = [PHImageManager defaultManager];
    [manager requestImageDataForAsset:asset options:nil resultHandler:^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) {
        // use `imageData` here
    }];
}

【讨论】:

  • 完美运行。感谢您的回答和示例,非常感谢。
  • 这会比同时使用UIImagePNGRepresentation 更好吗?
  • 这取决于图像,但一般来说,是的,如上所示参考原始图像要好得多。例如,我在 iPhone 上拍摄了一张 2448x3264 的照片,其原始资源为 1.5mb,JPEG @ 100% 质量为 5mb,PNG 为 13.3mb。这仍然比未压缩的 32mb 更好,而且 PNG 是无损的,但这是一个巨大的代价,尤其是当完整质量的图像很容易检索时。
  • 嗨@Rob...我在swift中使用不同的API来获取图像... func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) { imageToUpload = info[ UIImagePickerControllerOriginalImage] 为? UIImage } .....这里原始图像的大小比照片库中的图像大......关于这个为什么会发生的任何解释?
  • 发生这种情况是因为您没有检索资产本身,而是要求它检索转换为 UIImage 的资产,然后您可能会将其转换回 JPG 或 PNG 表示形式。关键是在 iOS 11 中获取UIImagePickerControllerPHAsset(在之前的 iOS 版本中为UIImagePickerControllerReferenceURL),并使用它从PHImageManager 中检索原始资产。见stackoverflow.com/a/32938728/1271826
猜你喜欢
  • 1970-01-01
  • 2014-01-10
  • 1970-01-01
  • 1970-01-01
  • 2013-12-20
  • 1970-01-01
  • 2012-10-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多