Iam尝试使用CFHTTP编写一个小型下载程序。不幸的是我不能使用非常简单的NSURL。我基本上想要一种异步方式来下载数据并将其存储在一个文件中。我还没有找到如何做异步方式,但我有一些代码与Sync方法不一样。问题是下载器没有下载完整的字节。我看到一些数据丢失导致最终文件损坏。这是我到目前为止的代码。
#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;
}
我得到的长度小于我的实际文件下载量。我不明白这段代码有什么问题。有人可以帮我这个吗?
答案 0 :(得分:1)
我还不知道这段代码出了什么问题。但我通过替换
解决了我的问题// 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;
}
希望这会有所帮助。如果有人能够指出原始代码出了什么问题,它仍然会很有用。
答案 1 :(得分:0)
我知道这件事已经很晚了,但是你的代码确实帮助了我(很难找到使用CFNetworking API获取响应正文字节的直接,完整的示例)。
无论如何,我认为错误是最后一个参数应该是FALSE(响应消息),而不是CFHTTPMessageCreateEmpty行中的TRUE(请求消息)。
CFHTTPMessageRef cfHttpResp = CFHTTPMessageCreateEmpty(kCFAllocatorDefault, FALSE);