0

CFHTTP を使用して小さなダウンローダーを作成しようとしています。残念ながら、非常に簡単な NSURL を使用できません。基本的に、データをダウンロードしてファイルに保存する非同期の方法が必要です。非同期の方法をまだ見つけていませんが、同期アプローチを使用したコードもいくつかありますが、うまくいきません。問題は、ダウンローダーが完全なバイトをダウンロードしないことです。一部のデータが欠落しているため、最終的なファイルが破損しています。ここに私がこれまでに持っているコードがあります。

#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;
}

私が得る長さは、実際のファイルダウンロードよりも短くなっています。このコードの何が問題なのかわかりません。誰かがこれで私を助けてくれますか?

4

2 に答える 2

1

このコードで何が問題になったのかはまだわかりません。しかし、私は交換することで問題を解決しました

//CFHTTPMessageRef cfHttpResp = CFHTTPMessageCreateEmpty(kCFAllocatorDefault, TRUE); CFMutableDataRef cfResp = CFDataCreateMutable(kCFAllocatorDefault, 0); CFHTTPMessageRef の代わりに MutableDataRef を使用するようになりました。ここで新しいコードを更新します。

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;
}

お役に立てれば。元のコードのどこが間違っていたのかを誰かが指摘できれば、それは依然として役に立ちます。

于 2013-04-15T23:02:40.307 に答える
0

私はこれを遅く知りましたが、あなたのコードは本当に私を助けてくれました (CFNetworking API を使用して応答本文のバイトを取得する簡単で完全な例を見つけるのは驚くほど困難です)。

とにかく、間違いはCFHTTPMessageCreateEmpty行の最後のパラメータがFALSE(応答メッセージ)ではなくTRUE(要求メッセージ)であるべきだったと思います。

CFHTTPMessageRef cfHttpResp = CFHTTPMessageCreateEmpty(kCFAllocatorDefault, FALSE);
于 2014-01-17T01:17:24.557 に答える