Objective c CFURL在下载时不提供完整数据
我正在尝试使用CFHTTP编写一个小型下载程序。不幸的是,我不能使用非常简单的NSURL。我基本上想要一种异步方式来下载数据并将其存储在文件中。我还没有找到如何以异步方式执行,但我有一些使用同步方法的代码,这些代码不能很好地工作。问题是下载程序没有下载完整的字节。我看到一些数据丢失,导致最终文件损坏。这是我到目前为止的代码Objective c CFURL在下载时不提供完整数据,objective-c,c,macos,core-foundation,Objective C,C,Macos,Core Foundation,我正在尝试使用CFHTTP编写一个小型下载程序。不幸的是,我不能使用非常简单的NSURL。我基本上想要一种异步方式来下载数据并将其存储在文件中。我还没有找到如何以异步方式执行,但我有一些使用同步方法的代码,这些代码不能很好地工作。问题是下载程序没有下载完整的字节。我看到一些数据丢失,导致最终文件损坏。这是我到目前为止的代码 #include <stdio.h> #include <string.h> #include <CoreFoundation/CoreFoun
#include <stdio.h>
#include <string.h>
#include <CoreFoundation/CoreFoundation.h>
#include <CFNetwork/CFNetwork.h>
#include <CFNetwork/CFHTTPStream.h>
int main(int argc, const char * argv[])
{
// insert code here...
const char *data;
FILE *fp;
CFShow(CFSTR("Hello, World!\n"));
CFURLRef cfUrl = CFURLCreateWithString(kCFAllocatorDefault, CFSTR("http://the.earth.li/~sgtatham/putty/0.62/x86/putty.zip"), NULL);
CFHTTPMessageRef cfHttpReq = CFHTTPMessageCreateRequest(kCFAllocatorDefault, CFSTR("GET"), cfUrl, kCFHTTPVersion1_1);
CFReadStreamRef readStream = CFReadStreamCreateForHTTPRequest(kCFAllocatorDefault, cfHttpReq);
CFReadStreamOpen(readStream);
CFHTTPMessageRef cfHttpResp = CFHTTPMessageCreateEmpty(kCFAllocatorDefault, TRUE);
CFIndex numBytesRead;
do {
const int nBuffSize = 1024;
UInt8 buff[nBuffSize];
numBytesRead = CFReadStreamRead(readStream, buff, nBuffSize);
if( numBytesRead > 0 )
{
CFHTTPMessageAppendBytes(cfHttpResp, buff, numBytesRead);
}
else if( numBytesRead < 0 )
{
CFStreamError error = CFReadStreamGetError(readStream);
printf ("Error %d", error.error);
}
} while ( numBytesRead > 0 );
CFStringRef myStatusLine = CFHTTPMessageCopyResponseStatusLine(cfHttpReq);
CFReadStreamClose(readStream);
CFDataRef cfResp = CFHTTPMessageCopyBody(cfHttpResp);
CFIndex length = CFDataGetLength(cfResp);
printf ("%lu\n", length);
CFShow(myStatusLine);
data = (const char*)CFDataGetBytePtr(cfResp);
fp = fopen("/var/tmp/Update.zip", "w");
if (fp == NULL) {
printf("ACnnot be opened\n");
} else {
fwrite(data, length, 1, fp);
fclose(fp);
}
printf ("Download done\n");
CFRelease(cfUrl);
CFRelease(cfHttpReq);
CFRelease(readStream);
CFRelease(cfHttpResp);
CFRelease(cfResp);
return 0;
}
#包括
#包括
#包括
#包括
#包括
int main(int argc,const char*argv[]
{
//在这里插入代码。。。
常量字符*数据;
文件*fp;
CFShow(CFSTR(“你好,世界!\n”);
CFURLRef cfUrl=CFURLCreateWithString(kCFAllocatorDefault,CFSTR(“http://the.earth.li/~sgtatham/putty/0.62/x86/putty.zip”),空);
CFHTTPMessageRef cfHttpReq=CFHTTPMessageCreateRequest(kCFAllocatorDefault,CFSTR(“GET”),cfUrl,kCFHTTPVersion1_1);
CFReadStreamRef readStream=CFReadStreamCreateForHTTPRequest(kcfalocatordefault,cfHttpReq);
CFReadStreamOpen(readStream);
CFHTTPMessageRef cfHttpResp=CFHTTPMessageCreateEmpty(kCFAllocatorDefault,TRUE);
CFIndex numBytesRead;
做{
常量int nBuffSize=1024;
UInt8 buff[nBuffSize];
numBytesRead=CFReadStreamRead(readStream、buff、nBuffSize);
如果(numBytesRead>0)
{
CFHTTPMessageAppendBytes(cfHttpResp、buff、numBytesRead);
}
否则如果(numBytesRead<0)
{
CFStreamError error=CFReadStreamGetError(readStream);
printf(“错误%d”,错误.Error);
}
}而(numBytesRead>0);
CFStringRef myStatusLine=CFHTTPMessageCopyResponseStatusLine(cfHttpReq);
CFReadStreamClose(readStream);
CFDataRef cfResp=CFHTTPMessageCopyBody(cfHttpResp);
CFIndex length=CFDataGetLength(cfResp);
printf(“%lu\n”,长度);
CFShow(myStatusLine);
数据=(const char*)CFDataGetBytePtr(cfResp);
fp=fopen(“/var/tmp/Update.zip”,“w”);
如果(fp==NULL){
printf(“无法打开ACN”);
}否则{
fwrite(数据,长度,1,fp);
fclose(fp);
}
printf(“下载完成\n”);
CFRelease(cfUrl);
CFRelease(cfHttpReq);
CFRelease(readStream);
CFRelease(cfHttpResp);
cfResp;
返回0;
}
我得到的长度小于我实际下载的文件长度。我不明白这个代码有什么问题。有人能帮我吗 我仍然不知道这段代码出了什么问题。但是我通过替换我的电脑解决了我的问题 //CFHTTPMessageRef cfHttpResp=CFHTTPMessageCreateEmpty(kCFAllocatorDefault,TRUE); CFMutableDataRef cfResp=CFDataCreateMutable(kCFAllocatorDefault,0); 我现在使用MutableDataRef而不是CFHTTPMessageRef。我将在这里升级新代码
int main(int argc, const char * argv[])
{
// insert code here...
const char *data;
FILE *fp;
CFShow(CFSTR("Hello, World!\n"));
CFURLRef cfUrl = CFURLCreateWithString(kCFAllocatorDefault, CFSTR("http://the.earth.li/~sgtatham/putty/0.62/x86/putty.zip"), NULL);
CFHTTPMessageRef cfHttpReq = CFHTTPMessageCreateRequest(kCFAllocatorDefault, CFSTR("GET"), cfUrl, kCFHTTPVersion1_1);
CFReadStreamRef readStream = CFReadStreamCreateForHTTPRequest(kCFAllocatorDefault, cfHttpReq);
CFReadStreamOpen(readStream);
//CFHTTPMessageRef cfHttpResp = CFHTTPMessageCreateEmpty(kCFAllocatorDefault, TRUE);
CFMutableDataRef cfResp = CFDataCreateMutable(kCFAllocatorDefault, 0);
CFIndex numBytesRead;
do {
const int nBuffSize = 1024;
UInt8 buff[nBuffSize];
numBytesRead = CFReadStreamRead(readStream, buff, nBuffSize);
if( numBytesRead > 0 )
{
CFDataAppendBytes(cfResp, buff, numBytesRead);
//CFHTTPMessageAppendBytes(cfHttpResp, buff, numBytesRead);
}
else if( numBytesRead < 0 )
{
CFStreamError error = CFReadStreamGetError(readStream);
printf ("Error %d", error.error);
}
} while ( numBytesRead > 0 );
CFReadStreamClose(readStream);
//CFDataRef cfResp = CFHTTPMessageCopyBody(cfHttpResp);
CFIndex length = CFDataGetLength(cfResp);
printf ("%lu\n", length);
data = (const char*)CFDataGetBytePtr(cfResp);
fp = fopen("/var/tmp/Update.zip", "w");
if (fp == NULL) {
printf("ACnnot be opened\n");
} else {
fwrite(data, length, 1, fp);
fclose(fp);
}
printf ("Download done\n");
CFRelease(cfUrl);
CFRelease(cfHttpReq);
CFRelease(readStream);
CFRelease(cfResp);
return 0;
}
int main(int argc,const char*argv[]
{
//在这里插入代码。。。
常量字符*数据;
文件*fp;
CFShow(CFSTR(“你好,世界!\n”);
CFURLRef cfUrl=CFURLCreateWithString(kCFAllocatorDefault,CFSTR(“http://the.earth.li/~sgtatham/putty/0.62/x86/putty.zip”),空);
CFHTTPMessageRef cfHttpReq=CFHTTPMessageCreateRequest(kCFAllocatorDefault,CFSTR(“GET”),cfUrl,kCFHTTPVersion1_1);
CFReadStreamRef readStream=CFReadStreamCreateForHTTPRequest(kcfalocatordefault,cfHttpReq);
CFReadStreamOpen(readStream);
//CFHTTPMessageRef cfHttpResp=CFHTTPMessageCreateEmpty(kCFAllocatorDefault,TRUE);
CFMutableDataRef cfResp=CFDataCreateMutable(kCFAllocatorDefault,0);
CFIndex numBytesRead;
做{
常量int nBuffSize=1024;
UInt8 buff[nBuffSize];
numBytesRead=CFReadStreamRead(readStream、buff、nBuffSize);
如果(numBytesRead>0)
{
CFDataAppendBytes(cfResp、buff、numBytesRead);
//CFHTTPMessageAppendBytes(cfHttpResp、buff、numBytesRead);
}
否则如果(numBytesRead<0)
{
CFStreamError error=CFReadStreamGetError(readStream);
printf(“错误%d”,错误.Error);
}
}而(numBytesRead>0);
CFReadStreamClose(readStream);
//CFDataRef cfResp=CFHTTPMessageCopyBody(cfHttpResp);
CFIndex length=CFDataGetLength(cfResp);
printf(“%lu\n”,长度);
数据=(const char*)CFDataGetBytePtr(cfResp);
fp=fopen(“/var/tmp/Update.zip”,“w”);
如果(fp==NULL){
printf(“无法打开ACN”);
}否则{
fwrite(数据,长度,1,fp);
fclose(fp);
}
printf(“下载完成\n”);
CFRelease(cfUrl);
CFRelease(cfHttpReq);
CFRelease(readStream);
cfResp;
返回0;
}
希望这有帮助。如果有人能指出原始代码出了什么问题,它仍然会很有用。我知道得这么晚了,但您的代码确实帮了我的忙(使用CFAPI获取响应正文字节的简单、完整的示例非常难找到) 无论如何,我认为错误在于CFHTTPMessageCreateEmpty行中的最后一个参数应该是FALSE(响应消息),而不是TRUE(请求消息)
CFHTTPMessageRef cfHttpResp = CFHTTPMessageCreateEmpty(kCFAllocatorDefault, FALSE);
您是否尝试过调试。看起来我的numBytesRead为0,这打破了循环。但是我的文件不完整。