Как определить размер (в байтах) загружаемого файла с помощью NSURLConnection?

StackOverflow https://stackoverflow.com/questions/2205167

Вопрос

Мне нужно знать размер файла, который я загружаю (в байтах) в свое приложение, используя NSURLConnection (GET).Вот мой полученный байтами код ниже, если это поможет.Что мне нужно знать, так это как получить размер файла в байтах, чтобы я мог использовать его для отображения UIProgressView.

- (void)connection:(NSURLConnection *)theConnection didReceiveData:(NSData *)data
// A delegate method called by the NSURLConnection as data arrives.  We just 
// write the data to the file.
{
#pragma unused(theConnection)
    NSInteger       dataLength;
    const uint8_t * dataBytes;
    NSInteger       bytesWritten;
    NSInteger       bytesWrittenSoFar;

    assert(theConnection == self.connection);

    dataLength = [data length];
    dataBytes  = [data bytes];

    bytesWrittenSoFar = 0;
    do {
        bytesWritten = [self.fileStream write:&dataBytes[bytesWrittenSoFar] maxLength:dataLength - bytesWrittenSoFar];
        assert(bytesWritten != 0);
        if (bytesWritten == -1) {
            [self _stopReceiveWithStatus:@"File write error"];
            break;
        } else {
            bytesWrittenSoFar += bytesWritten;

    } while (bytesWrittenSoFar != dataLength);
}
Это было полезно?

Решение

[длина данных] возвращает размер данных в байтах, который должен дать вам цифру, которую вы ищете.

Но NSData предоставляет -writeToFile:атомарно:и -writeToFile: параметры: ошибка методов записи данных на диск, поэтому я не знаю, почему вы пишете свой собственный файл ввода-вывода.

Другие советы

Я полагаю, что код взят из примера кода SimpleURLConnections от Apple.Вот прямая цитата из метода NSURLConnection от Apple "connection:didReceiveData:"

"Делегат должен объединить содержимое каждого доставленного объекта данных для создания полных данных для загрузки URL".

NSData не предоставляет методов для постепенной записи в файл, он записывает все это сразу, поэтому я думаю, что этот метод постепенной записи в NSOutputStream, здесь называемый FileStream, является правильным.Использование dataLength в этом коде вернет только длину данных, которые были отправлены из NSURLConnection делегату в одном вызове "connection:didReceiveData:", а не общую длину данных для всего соединения.Чтобы достичь этого, я добавил дополнительные свойства:

@property (nonatomic, assign)   long long dataWrittenForWholeConnection;
@property (nonatomic, assign)   long long dataLengthOfWholeConnection;

В связи: Получил ли ответ:Я использовал метод NSURLResponse expectedContentLength, чтобы получить правильную оценку размера файла получаемых данных для всего соединения.

self.dataWrittenForWholeConnection = 0;
self.dataLengthOfWholeConnection = [httpResponse expectedContentLength];

В связи:didReceiveData:Я изменил следующее:

// bytes written for current "connection:didReceiveData:" call
bytesWrittenSoFar += bytesWritten;
// cumulative data written for connection so far
self.dataWrittenForWholeConnection += bytesWritten;

// also update the progress bar
if (self.dataLengthOfWholeConnection != NSURLResponseUnknownLength) {
    self.progressView.progress =
        ((float)self.dataWrittenForWholeConnection / (float)self.dataLengthOfWholeConnection);
}

К концу подключения это должно быть правдой:

assert(dataWrittenForWholeConnection == dataLengthOfWholeConnection);

Вот распечатка из того же кода SimpleURLConnections с моими изменениями, чтобы показать, что происходит на самом деле:

connection:didReceiveResponse:
Full size of data is 8789 bytes

connection:didReceiveData:
Data has 1408 bytes
Progress bar is at: 0.160200
1408 bytes of data were written, 1408 bytes so far

connection:didReceiveData:
Data has 1408 bytes
Progress bar is at: 0.320401
1408 bytes of data were written, 2816 bytes so far

connection:didReceiveData:
Data has 1408 bytes
Progress bar is at: 0.480601
1408 bytes of data were written, 4224 bytes so far

connection:didReceiveData:
Data has 1408 bytes
Progress bar is at: 0.640801
1408 bytes of data were written, 5632 bytes so far

connection:didReceiveData:
Data has 1408 bytes
Progress bar is at: 0.801001
1408 bytes of data were written, 7040 bytes so far

connection:didReceiveData:
Data has 1749 bytes
Progress bar is at: 1.000000
1749 bytes of data were written, 8789 bytes so far

connectionDidFinishLoading:
Connection Finished. 8789/8789 bytes of data were written.

Кроме того, метод NSOutputStream "write:maxLength:" возвращает "количество фактически записанных байт", поэтому по какой-то причине он может предпочесть не записывать все данные сразу в рамках одного вызова "connection:didReceiveData:", поэтому для проверки этого используется цикл do / while.Но в этом примере он записывает все данные за одну итерацию do / while.

Кроме того, вы можете использовать вместо этого NSFileHandle , и это всегда будет записывать все данные, отправляемые при каждом соединении:didReceiveData:вызов, также это инкрементный.Обратите внимание, однако, что writeData:является синхронным.

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
    // write data to file handler
    unsigned long long dataLength = [data length];

    NSLog(@"Writing %qu bytes at %qu bytes", dataLength, [self.fileHandle offsetInFile]);
    [self.fileHandle writeData:data];
    NSLog(@"Wrote %qu bytes, now at %qu bytes", dataLength, [self.fileHandle offsetInFile]);
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top