【问题标题】:iPhone - Corrupt JPEG data for image received over HTTPiPhone - 通过 HTTP 接收的图像的 JPEG 数据损坏
【发布时间】:2010-11-07 02:05:00
【问题描述】:

我通过 HTTP 获取图像,使用 NSURLConnection,如下 -

NSMutableData *receivedData;

- (void)getImage {
    self.receivedData = [[NSMutableData alloc] init];
    NSURLConnection *theConnection = // create connection
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {    
   [receivedData appendData:data];
}

-(void)connectionDidFinishLoading:(NSURLConnection *)connection {
   [connection release];

   UIImage *theImage = [UIImage imageWithData:receivedData];
}

通常它工作得很好,但有时我会看到这个被记录 - :损坏的 JPEG 数据:数据段的过早结束

此时,图像还没有完全渲染。我会看到大概 75%,然后右下角是一个灰色框。

关于如何解决此问题的任何想法?我是不是在不正确地构建我的图像?

【问题讨论】:

  • 我已经下载了很多图片,还没有看到这个。你的图像非常大吗?这是否发生在其他设备(计算机、模拟器)上?
  • 不是特别大,不是。我确实在 iPhone 和模拟器上都看到了它(但不是通过网络浏览器点击图像)。
  • 请同时检查您的互联网连接。

标签: iphone cocoa-touch uiimage


【解决方案1】:

您的 HTTP 代码看起来正确。加载完成后,您可能希望记录 receivedData 的大小,并将其与服务器上图像的预期大小进行比较。如果它是预期的大小,那么可能图像本身在服务器上已损坏。

【讨论】:

  • 谢谢,这帮了很多忙。通过这样做,我意识到这是我自己的编程错误(我不小心触发了两次请求)。
  • 我在做和 bpapa 一样的事情。似乎如果您向同一个 URL 启动 2 个不同的 NSURLConnections,最终结果将是损坏的数据。
  • 我遇到了完全相同的问题,而且确实是出于相同的原因:2 个连接到同一个图像。
  • 创建错误是因为两个连接共享相同的数据源。在构建必须同时触发特定任务的应用程序时(您似乎无意中这样做了:)),您要么必须为每个连接(一对一)拥有一个唯一的数据源,要么创建一个信号量以便您的可变数据source 没有同时使用多个连接的结果进行序列化(竞争条件)。最终结果是创建损坏或不完整的数据! (你所经历的)。
  • @bpapa - 您在代码中的哪个位置触发了两次请求?根据我的日志输出,我想我也在做同样的事情,但不明白为什么只有某些照片会被调用两次。
【解决方案2】:

ASI-HTTP 可以解决这个问题。

NSURL *coverRequestUrl = [NSURL URLWithString:imageStringURL];
ASIHTTPRequest *coverRequest = [[ASIHTTPRequest alloc] initWithURL:coverRequestUrl];
[coverRequest setDelegate:self];
[coverRequest setDidFinishSelector:@selector(imageRecieved:)];

[appDelegate.queue addOperation:coverRequest];
[appDelegate.queue go];

我在 appDelegate 中的队列变量是 ASINetwork 队列对象。因为我发送异步请求,所以我使用它。

- (void)imageRecieved:(ASIHTTPRequest *)response
{
    UIImage *myImage = [UIImage imageWithData:[response responseData]];
}

【讨论】:

    【解决方案3】:

    我通过使用 NSMutableDictionary 解决了这个问题。

    NSMutableDictionary *dataDictionary;
    

    在我的 loadData 函数中,我定义了我的数据:

    NSMutableData *receivedData = receivedData = [[NSMutableData alloc] init];
    

    然后我将数据加载到我的字典中,其中键是 [theConnection 描述],对象是我的数据。

    [dataDictionary setObject:receivedData forKey:[theConnection description]];
    

    这样,在委托中,我可以为传递给委托的连接查找正确的数据对象并保存到正确的数据实例,否则我最终会遇到 JPEG 修改/损坏问题。

    在 didReceiveData 中,我输入了:

    //get the object for the connection that has been passed to connectionDidRecieveData and that object will be the data variable for that instance of the connection.
    NSMutableData *theReceivedData = [dataDictionary objectForKey:[connection description]];
    
    //then act on that data
    [theReceivedData appendData:data];
    

    同样,在 didReceiveResponse 中,我输入:

    NSMutableData *theReceivedData = [dataDictionary objectForKey:[connection description]];
    [theReceivedData setLength:0];
    

    在 connectionDidFinishLoading 中: NSMutableData *theReceivedData = [dataDictionary objectForKey:[connection description]]; img = [[UIImage alloc] initWithData:theReceivedData];

    而且这似乎工作得很好。顺便说一句,我的代码基于Apple's tutorial for NSUrlConnection,并添加了一个 NSMutableDictionary 来跟踪各个连接。我希望这有帮助。如果您希望我发布完整的图像处理代码,请告诉我。

    【讨论】:

    • 我用同样的方法。效果很好。确保在发送请求之前分配并初始化字典中的数据对象。否则你会犯同样的错误
    【解决方案4】:

    我也看到了。如果您将数据保存到文件中,然后将数据读回图像中,则可以完美运行。我怀疑jpeg图像数据中有http头信息。

    希望有人找到解决方案,因为保存到文件的解决方法很糟糕。

    // problem
    
    UIImage *newImage = [UIImage imageWithData:receivedData];
    
    // crappy workaround
    
    [receivedData writeToFile:[NSString stringWithFormat:@"a.jpg"] atomically:NO];
    UIImage *newImage = [UIImage imageWithContentsOfFile:@"a.jpg"];

    【讨论】:

    • 试过了,没有任何改变
    【解决方案5】:

    使用receivedData = [NSData dataWithBytes:receivedData.bytes length:receivedData.length] 复制 NSData 内容也可能会有所帮助(而且它比保存到磁盘和从磁盘读取更有效)。

    一个可能的原因是原始 receivedData 对象没有保留其内容(例如,当使用 [NSData dataWithBytesNoCopy:length:] 创建时)并且您在它们被释放后尝试读取它们。

    这很可能是当您在创建NSData 对象的线程的另一个线程上遇到此问题时。

    【讨论】:

      猜你喜欢
      • 2014-08-16
      • 2014-07-01
      • 2011-06-22
      • 2013-05-04
      • 1970-01-01
      • 2021-09-08
      • 2012-10-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多