Попытка загрузить файл, используя CFHTTPMessage - PullRequest
1 голос
/ 12 января 2012

Возникла проблема с загрузкой файла с использованием загрузки HTTP-файла. Протокол, используемый согласно клиент-серверному пониманию, заключается в том, что заголовки HTTP-запроса для Сначала следует загрузить txn, за которым следует поток, который должен содержать данные XML-запроса, а затем данные буфера файлов.

Теперь заголовки запросов достигают, и сервер после чтения заголовков начинает читать поток. Он также получает XML-запрос из потока.

После этого сервер считывает данные файла из потока. После завершения загрузки файла я пытаюсь загрузить тот же файл. На сервере я вижу, что файл находится там, и он показывает правильный размер.

После того, как я скачал файл, я обнаружил, что файл обрезан в конце (в случае файла jpg) или отсутствует какой-либо конечный текст (в случае файла txt).

Согласно логике моего проекта, данные передаются в виде фрагментов по 8 КБ. Я проверил, что последний фрагмент, который меньше 8 КБ, - это недостающие данные, вызывающие обрезку изображений. Я также проверил, что последний блок содержит действительные данные в буфере, сформированном API-интерфейсом fileHandler. Я посылаю несколько фрагментов кода, которые я использовал для логики записи.

Можете ли вы указать какую-либо конкретную причину, по которой последний чанк не передается в потоковом режиме, или некоторые ненужные данные передаются вместо последнего чанка?

Фрагмент кода для создания Writestream:

const UInt8 *uploadBuf;
uploadBuf = (const UInt8*)malloc(totLen);

CFReadStreamRef readStreamForBody = CFReadStreamCreateWithBytesNoCopy(kCFAllocatorDefault, uploadBuf, (CFIndex)totLen, kCFAllocatorNull);
CFReadStreamRef readStreamForUpload = CFReadStreamCreateForStreamedHTTPRequest(kCFAllocatorDefault, messageRef, readStreamForBody);

if (CFReadStreamOpen(readStreamForUpload) == TRUE)
{   
    CFWriteStreamRef writeStream = CFWriteStreamCreateWithBuffer(kCFAllocatorDefault, (UInt8*)uploadBuf, (CFIndex)totLen);
    if (CFWriteStreamOpen(writeStream) == FALSE)
    {
        CFErrorRef streamError = CFWriteStreamCopyError(writeStream);
        CFStringRef streamErrorString = CFErrorCopyDescription(streamError);
        CFShow(streamErrorString);
        CFRelease(streamError);
        CFRelease(streamErrorString);

        CFWriteStreamClose(writeStream);
        CFRelease(writeStream);
        writeStream = NULL;
    }
    else 
    {
        Boolean hasBytes = FALSE;
        CFStreamStatus  streamStatus = CFWriteStreamGetStatus(writeStream);
        do
        {
            while ((hasBytes == FALSE) &&
                ((streamStatus != kCFStreamStatusNotOpen) &&
                (streamStatus != kCFStreamStatusAtEnd) &&
                (streamStatus != kCFStreamStatusClosed) &&
                (streamStatus != kCFStreamStatusError)))
            {
                CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.25, false);
                hasBytes = CFWriteStreamCanAcceptBytes(writeStream);
                streamStatus = CFWriteStreamGetStatus(writeStream);
            }
        } while (hasBytes != TRUE);

Фрагмент кода для сохранения записанного потока:

[self setWriteStreamForFile:writeStream];
[[MyHTTPLastRequestList lastRequestList] setObject:self forKey:[self sessionKey]];

Фрагмент кода для записи буфера в потоковый поток:

- (void) write:(const void*)fileBuffer numBytes:(NSUInteger)fileBufSize
{
    MyThreadSafeDictionary *lastRequestList = [MyHTTPLastRequestList lastRequestList];
    NSString *sessionKey = [self sessionKey];

    BOOL noResponse = YES;
    while (noResponse)
        noResponse = ([lastRequestList objectForKey:sessionKey] == nil);

    MyHTTPMessage *httpFileUploadMsg = (MyHTTPMessage*)[lastRequestList objectForKey:sessionKey];   
    CFIndex totalLen = [httpFileUploadMsg totalLength];
    CFIndex sentLen = [httpFileUploadMsg sentLength];

    NSData *chunkData = [[[NSData dataWithBytes:fileBuffer length:fileBufSize] retain] autorelease];
    sentLen += (CFIndex)fileBufSize;
    CFIndex bytesRemaining = totalLen - sentLen;
    CFIndex bytesWritten = 0;

    CFWriteStreamRef writeStream = [httpFileUploadMsg writeStreamForFile];
    if (bytesRemaining > 0)
    {
        CFWriteStreamRef writeStream = [httpFileUploadMsg writeStreamForFile];
        bytesWritten = CFWriteStreamWrite(writeStream, (const UInt8*)[chunkData bytes], (CFIndex)fileBufSize);

        [httpFileUploadMsg setSentLength:sentLen];

        NSLog(@"Bytes written to stream = %d",(NSInteger)sentLen);
        [httpFileUploadMsg setWriteStreamForFile:writeStream];
    }
    else  
    {       
        @try 
        {
            bytesWritten = CFWriteStreamWrite(writeStream, (const UInt8*)[chunkData bytes], (CFIndex)fileBufSize);

            if (bytesWritten == 0)
            {
                NSLog(@"ERROR :: Stream Filled to capacity");
            }
            else if (bytesWritten < 0)
            {
                NSLog(@"ERROR :: Write failed.");
                CFErrorRef streamError = CFWriteStreamCopyError(writeStream);
                CFStringRef streamErrorString = CFErrorCopyDescription(streamError);
                CFShow(streamErrorString);
                CFRelease(streamError);
                CFRelease(streamErrorString);
            }
            else 
            {
                NSLog(@"Write Success");            
            }
        }
        @catch (NSException* localException) 
        {
            NSLog(@"Exception raised - %@",[localException name]);
            [localException raise];
        }

        NSLog(@"Sending to the server");
        CFReadStreamRef readStreamForUpload = [httpFileUploadMsg readStreamForHTTPResponse];
        CFStreamStatus  rStreamStatus = CFReadStreamGetStatus(readStreamForUpload);
        Boolean parentStreamHasBytes = FALSE;
        do
        {
            while ((parentStreamHasBytes == FALSE) &&
                ((rStreamStatus != kCFStreamStatusNotOpen) &&
                (rStreamStatus != kCFStreamStatusAtEnd) &&
                (rStreamStatus != kCFStreamStatusClosed) &&
                (rStreamStatus != kCFStreamStatusError)))
            {
                CFRunLoopRunInMode (kCFRunLoopDefaultMode, 0, false);
                parentStreamHasBytes = CFReadStreamHasBytesAvailable(readStreamForUpload);
                rStreamStatus = CFReadStreamGetStatus(readStreamForUpload);
            }
        } while (parentStreamHasBytes != TRUE);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...