4

您好我想运行一个线程并检查文件的当前下载大小。

这就是我使用的

UIImage *image = [[UIImage alloc] initWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://lasp.colorado.edu/home/wp-content/uploads/2011/03/suncombo1.jpg"]]];

NSString *docDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];

NSString *jpegFilePath = [NSString stringWithFormat:@"%@/test.jpeg",docDir];
NSData *data2 = [NSData dataWithData:UIImageJPEGRepresentation(image, 1.0f)];//1.0f = 100% quality
[data2 writeToFile:jpegFilePath atomically:YES];
downloadStatus.text =[NSString stringWithFormat:@"size: %zd", malloc_size(data2)];

[image release];

我也尝试将 malloc_size(data2) 更改为图像,但这又不是真正的结果。我知道这没有线程并且在下载过程中不检查但是我应该在这里使用什么来查看文件大小?

4

3 回答 3

5

几点观察:

  1. 您的问题假定您尝试检索大小的尝试NSData失败了。他们不是。获取 a 大小的正确方法NSData是 via length

  2. 但是,您的困惑源于一个错误的假设,即在往返过程中采用外部生成的 JPEGUIImageUIImageJPEGRepresentation会产生相同的NSData. 这本来是极不可能的。有太多不同的 JPG 设置可能会更改(请参阅JPEG 维基百科页面)。我们当然不知道原始文件使用了哪些设置。我知道UIImage和/或UIImageJPEGRepresentation更改了文件的颜色空间。我敢打赌它还会做很多其他事情。

  3. 所以你的结果是正确的。原始文件为 2.6mb,生成的文件为 4.5mb。如果将compressionQuality1.0 更改为 0.99,生成的文件只有 1.4mb!但是如果你想要原始文件,只需先保存它(就像我在下面做的那样)。

考虑以下代码,它下载图像文件,保存它,将其加载到 aUIImage中,通过 重新提取它UIImageJPEGRepresentation,并保存图像的另一个副本:

// let's make filenames where we'll store the files

NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *suncomboOrig = [documentsPath stringByAppendingPathExtension:@"suncombo1-orig.jpg"];
NSString *suncomboReprocessed = [documentsPath stringByAppendingPathExtension:@"suncombo1-reprocessed.jpg"];

// let's download the original suncombo1.jpg and save it in Documents and display the size

NSURL *url = [NSURL URLWithString:@"http://lasp.colorado.edu/home/wp-content/uploads/2011/03/suncombo1.jpg"];
NSData *data = [NSData dataWithContentsOfURL:url];
NSLog(@"original = %d", [data length]);
[data writeToFile:suncomboOrig atomically:NO];

// let's load that into a UIImage

UIImage *image = [UIImage imageWithData:data];

// let's extract data out of the image and write that to Documents, too, also logging the size of that

NSData *data2 = UIImageJPEGRepresentation(image, 1.0);
NSLog(@"reprocessed = %d", [data2 length]);
[data2 writeToFile:suncomboReprocessed atomically:NO];

它的作用是报告:

2012-12-13 22:30:39.576 imageapp [90647:c07] 原始 = 2569128
2012-12-13 22:30:40.141 imageapp [90647:c07] 重新处理 = 4382876

因此,我保存的第一个文件(我怀疑它与您服务器上的文件相同)是 2.5mb,并且在往返于 aUIImage并通过 4.3mb 重新提取后的文件。如果我查看上面代码保存的两个文件,我可以确认这些NSData大小是正确的。


我最初的答案是基于这样的假设,即 OP 要么无法检索 a 的大小,要么NSData简单问题背后存在一些微妙的问题(例如想要在下载开始之前获得大小)。无论如何,我已经在上面扩展了我的答案,但出于历史目的,我会保留我的原始答案:

原答案:

NSData属性length告诉您下载了多少字节。例如[data2 length]

如果它真的很大,您可以使用NSURLConnection异步下载它,这取决于您的 Web 服务器,可能会在方法中开始下载之前提供总文件大小didReceiveResponse(使用参数expectedContentLength中的属性NSHTTPURLResponse *response)。

下载的另一个好处NSURLConnection是您不必在下载时将整个文件加载到内存中,而是可以将其直接流式传输到持久存储,这在您下载多个大文件时特别有用同时。如果您正在下载大小合理的文件,使用NSURLConnection下载 是多余的,但是在下载大文件并且您想要一个进度指示器(或想要在下载开始之前获取文件大小)时它可能会很好。

但是,如果您只想知道下载了多少字节,请NSData使用length.

于 2012-12-14T01:04:43.603 回答
4

您可以只使用 CFILE类来获取文件大小。

 FILE * handle = fopen([jpegFilePath UTF8String], "r");
 fseek(handle, EOF); // seek to end of file
 int size = ftell(handle); // returns position in bytes
 fclose();
于 2012-12-14T01:04:30.147 回答
3

因为您说“当前”大小并提到了一个线程,所以我猜您正在尝试确定收到的文件大小。在这种情况下,您可以从 中免费获取线程NSURLConnection,并且可以从委托方法中获取接收到的数据大小......

为下载的数据创建一个实例变量:

@property (nonatomic, strong) NSMutableData *data;

创建并启动连接:

NSURL *url = [NSURL URLWithString:@"http://lasp.colorado.edu/home/wp-content/uploads/2011/03/suncombo1.jpg"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];

self.data = [NSMutableData data];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];

在NSURLConnectionDataDelegate中实现所需的方法。对于您的问题,特殊部分是:

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

    NSUInteger bytesSoFar = [self.data length];
    // you're on the app main thread here, so you can do something
    // to the UI to indicate progress
    downloadStatus.text = [NSString stringWithFormat@"size: %d", bytesSoFar];
}

关于协议其余部分的好文档在这里。连接完成后,您可以像使用dataWithContentsOfURL...

- (void)connectionDidFinishLoading:(NSURLConnection *)connection {

    UIImage *image = [[UIImage alloc] initWithData:self.data];
    downloadStatus.text = [NSString stringWithFormat@"size: %d", [self.data length]];
}
于 2012-12-14T01:26:12.940 回答