You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

使用multipart/form-data POST上传图片至后端时出现旋转问题求助

问题原因及解决方案

这个问题我之前做iOS图片上传时也踩过一模一样的坑!核心原因是图片的EXIF方向元数据在导出时没有被正确处理:

  • 当你用iPhone竖屏拍照时,图片的像素其实是横向存储的,只是在EXIF元数据里标记了「需要旋转90度才能正确显示」;
  • UIImage加载时会自动读取这个EXIF信息,所以你在App里看到的图片是正的;
  • UIImageJPEGRepresentation默认会忽略这个方向信息,直接按像素的原始存储方向导出JPEG数据,导致后端拿到的是未旋转的原始像素图,自然就显示歪了。

解决办法:先修正图片方向,再导出数据

你需要先把UIImage转换成「不带方向标记的正确像素方向」的图片,再生成JPEG数据。可以添加一个工具方法来处理:

- (UIImage *)fixImageOrientation:(UIImage *)image {
    // 如果图片方向本来就是正常的,直接返回
    if (image.imageOrientation == UIImageOrientationUp) return image;
    
    CGAffineTransform transform = CGAffineTransformIdentity;
    
    // 根据图片方向计算旋转/平移变换
    switch (image.imageOrientation) {
        case UIImageOrientationDown:
        case UIImageOrientationDownMirrored:
            transform = CGAffineTransformTranslate(transform, image.size.width, image.size.height);
            transform = CGAffineTransformRotate(transform, M_PI);
            break;
        case UIImageOrientationLeft:
        case UIImageOrientationLeftMirrored:
            transform = CGAffineTransformTranslate(transform, image.size.width, 0);
            transform = CGAffineTransformRotate(transform, M_PI_2);
            break;
        case UIImageOrientationRight:
        case UIImageOrientationRightMirrored:
            transform = CGAffineTransformTranslate(transform, 0, image.size.height);
            transform = CGAffineTransformRotate(transform, -M_PI_2);
            break;
        default:
            break;
    }
    
    // 处理镜像情况
    switch (image.imageOrientation) {
        case UIImageOrientationUpMirrored:
        case UIImageOrientationDownMirrored:
            transform = CGAffineTransformTranslate(transform, image.size.width, 0);
            transform = CGAffineTransformScale(transform, -1, 1);
            break;
        case UIImageOrientationLeftMirrored:
        case UIImageOrientationRightMirrored:
            transform = CGAffineTransformTranslate(transform, image.size.height, 0);
            transform = CGAffineTransformScale(transform, -1, 1);
            break;
        default:
            break;
    }
    
    // 创建上下文并绘制修正后的图片
    CGContextRef ctx = CGBitmapContextCreate(NULL, image.size.width, image.size.height,
                                             CGImageGetBitsPerComponent(image.CGImage), 0,
                                             CGImageGetColorSpace(image.CGImage),
                                             CGImageGetBitmapInfo(image.CGImage));
    CGContextConcatCTM(ctx, transform);
    
    switch (image.imageOrientation) {
        case UIImageOrientationLeft:
        case UIImageOrientationLeftMirrored:
        case UIImageOrientationRight:
        case UIImageOrientationRightMirrored:
            CGContextDrawImage(ctx, CGRectMake(0,0,image.size.height,image.size.width), image.CGImage);
            break;
        default:
            CGContextDrawImage(ctx, CGRectMake(0,0,image.size.width,image.size.height), image.CGImage);
            break;
    }
    
    CGImageRef cgimg = CGBitmapContextCreateImage(ctx);
    UIImage *fixedImage = [UIImage imageWithCGImage:cgimg];
    
    // 释放资源
    CGContextRelease(ctx);
    CGImageRelease(cgimg);
    
    return fixedImage;
}

然后修改你代码里生成图片数据的部分:

// 替换原来的UIImageJPEGRepresentation调用
UIImage *fixedImage = [self fixImageOrientation:imageToUpload];
// 这里建议不要用0作为压缩质量,0会导致图片严重模糊,0.8是兼顾体积和清晰度的最优值
NSData *imageData = UIImageJPEGRepresentation(fixedImage, 0.8);

额外提示

当然你也可以选择在后端解析EXIF方向并旋转图片,但前端处理会更可靠——毕竟不同后端语言/框架对EXIF的解析逻辑可能有差异,前端统一修正后,后端拿到的就是直接可用的正确方向图片。

内容的提问来源于stack exchange,提问作者iVJ

火山引擎 最新活动