我在尝试将图像从我的Java网络服务器传输到我的Amazon S3存储桶时遇到了这个奇怪的问题。我正在为Android和iOS(使用Swift)开发移动应用程序,允许用户将图像从他们的设备上传到服务器。
图像(Android的Bitmaps和iOS的UIImage)在发送到我的网络服务器(用Java制作以符合HTTP / 1.1标准)之前都转换为Base 64。数据完整地到达服务器(意味着通过在发送之前打印基础64,并且在它到达服务器之后,它们是相同的)。从那里我将String解码为字节数组。我已将此问题与实际发送到Amazon S3存储桶的过程隔离开来。以下面的代码段为例:
//image is a byte array, and imageid a String
InputStream is = new ByteArrayInputStream(image);
AmazonS3 s3 = new AmazonS3Client();
ObjectMetadata meta = new ObjectMetadata();
meta.setContentType("image/jpeg");
meta.setContentLength(image.length);
s3.putObject(new PutObjectRequest("bucket", "images/" + imageid + ".jpg", is, meta));
此代码适用于Android,其中图片上传为1080x1080而没有任何问题。但是,当我尝试从iPhone上传图像时,分辨率变为1080x1081。由此感到困惑,我决定尝试在本地保存图像,并使用ImageIO将其发送到服务器。奇怪的是,使用:
BufferedImage img = ImageIO.read(new ByteArrayInputStream(image));
File f = new File("image.jpg"); //Removed file creation for brevity
ImageIO.write(img, "jpg", f);
当我在本地图像上使用Imagick的“识别”命令时,输出为:
image.jpg JPEG 1080x1080 1080x1080+0+0 8-bit DirectClass 53.4KB 0.000u 0:00.000
然而,当我从S3存储桶传输图像并执行相同操作时,我得到:
image2.jpg JPEG 1080x1081 1080x1081+0+0 8-bit DirectClass 56.2KB 0.000u 0:00.000
同样,只有在iOS上传时才会出现这种情况。图像本身仍然有效,打开时没有问题。例如:
(相机朝下时拍摄照片,因此暗图像)
我怀疑这个问题可能与图像编码到Base 64的方式有所不同。我使用Bouncycastle库在Android上进行编码,以及在网络服务器上进行解码,以及在swift中使用NSData函数,如下所述:
let imageData = UIImageJPEGRepresentation(normImg, 0.4)
let base64 = NSString(data: imageData!.base64EncodedDataWithOptions(NSDataBase64EncodingOptions(rawValue: 0)), encoding: NSUTF8StringEncoding) as! String
最令我困惑的是~3KB的数据(对于每个RGB像素3个字节的1080个额外像素有意义)似乎只是出现在哪里,以及为什么它似乎被隔离到iOS。
希望我对我的问题以及我为提供尽可能多的信息所做的调试已经足够清楚了。如果您需要更多信息,请告诉我们!
编辑:只需运行测试,然后通过命令行将1080x1080图像上传到S3存储桶。它还增加了额外的像素。
编辑2:决定更改文件上传过程的工作方式。它不再被转换为base 64,并且UIImage的NSData正被转换为字节(UInt8)数组并上传。这仍然导致了具有额外像素的相同结果,这排除了我最初的猜测,即它与base64编码有关。另一方面,Android似乎仍能正常运行,这让我相信图像的二进制数据无论出于何种原因都不完全有效。我相信EXIF数据在Android和iOS之间的格式不同,但我不知道是什么原因造成的。