使用libcurl进度数据

making use of libcurl progress data

本文关键字:数据 libcurl 使用      更新时间:2023-10-16

在Xcode中设置一堆curl_easy_setopt函数用于上传文件到服务器/API,并且(经过大量的试验和错误)它都像魅力一样工作。在经历了其他几个问题之后,我也设法设置了一个简单的CURLOPT_PROGRESSFUNCTION,看起来像这样:

static int my_progress_func(void *p,
                        double t,
                        double d,
                        double ultotal,
                        double ulnow)
{
printf("(%g %%)n", ulnow*100.0/ultotal);
// globalProgressNumber = ulnow*100.0/ultotal;
return 0;
}

随着上传的进行"0%.. "16% . .58% . .100%"是输出到控制台;灿烂的。我不能做的是实际使用这个数据(globalProgressNumber) eg。for我的NSProgressIndicator;CURL劫持了我的应用程序,不允许任何其他输入/输出,直到进度完成。

我尝试从my_progress_func更新IBOutlets(例如。[_myLabel setStringValue:globalProgressNumber];),但静态int函数不允许这样做。也不允许[self],所以发送到NSNotificationCenter是不可能的:[[NSNotificationCenter defaultCenter] postNotificationName:@"Progressing" object:self];

我的curl函数从我的主类/window (NSPanel)运行。

关于如何在我的。xib上实现实时/更新元素有什么好的建议吗?

旋度[…在进度完成之前,不允许任何其他输入/输出。

你是从主线程调用curl_easy_perform吗?如果是,你不应该这样做,因为这个函数是同步的,也就是说,它会阻塞直到传输完成。

换句话说,长时间运行的任务(例如网络I/O)必须在单独的线程上运行,而UI代码(例如更新标签的文本)必须在主线程上运行。

如何实现实时/更新元素

你一定要注意在一个单独的线程中执行curl传输。

这可以很容易地实现,通过包装到一个自定义协议的NSOperation通知进度委托(例如你的视图控制器):

  • 将您的操作推入NSOperationQueue
  • 操作队列将注意分离传输并将其运行到另一个线程中,
  • 在操作端,您仍然应该使用进度函数,并通过CURLOPT_PROGRESSDATA curl选项将操作对象设置为不透明对象。这样,每次调用progress函数时,都可以通过强制转换void *clientp不透明指针来检索操作对象。然后通知委托当前进程在主线程(例如performSelectorOnMainThread),以确保您可以执行UI更新,如刷新您的NSProgressIndicator

作为NSOperation的替代方案,您还可以使用大中央调度(GCD)和块。如果可能的话,我强烈建议你使用BBHTTP,这是一个ios5 +和OSX 10.7+的libcurl客户端(BBHTTP使用GCD和块)。

供参考:这里有一个来自BBHTTP的例子,说明了如何使用上载进度块轻松执行文件上传-这是针对iOS的,但应该可以直接用于OS x。