Возникла проблема с загрузкой файла с использованием загрузки 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);