Разбейте изображение / jpeg на фрагменты и свяжите в nsdictionary для отправки JSON в iOS

#ios #image #sockets #nsdata #outputstream

#iOS #изображение #сокеты #nsdata #outputstream

Вопрос:

РЕДАКТИРОВАТЬ: я не очень хорошо объяснил работу сервера и приношу свои извинения за то же самое. Итак, вот две вещи, в которых сервер работает (ожидает данные от клиентов)

1) Сервер имеет ограничение по размеру для получения данных изображения. Ожидается, что изображения будут разбиты на фрагменты массива байт 2) Сервер ожидает получения этих фрагментов массива байт через JSON.

Итак, я предполагаю, что это приводит к следующему на стороне клиента

1) Мне нужно разбить изображение на части 2) Создать массив байтов для каждой части 3) Связать этот массив байтов с помощью JSON и отправить с сервера

После получения сервером они создаются сервером в виде изображения.

Я пытаюсь достичь вышеупомянутой цели с помощью следующего подхода (я сохраняю файл изображения в NSData, затем создаю байтовый буфер и сохраняю фрагменты NSData файла изображения в этом буфере. Опубликуйте, что я привязываю этот буфер с помощью JSON)

Ниже приведен код для описанного выше подхода:

-(void)dividepacketId:(int)pktId fileData:(NSData*)dt //dt содержит NSData файла изображения {

 Byte buffer[20480];
long long dtLength,from=0;
long long len=[dt length];
BOOL b=YES;
while (b)
{
    int k=0,indexCont=0;
    if(len>20480)
    {
      dtLength=20480;
    }
    else
    {
        dtLength=len;
        b=NO;
    }
    [dt getBytes:buffer range:NSMakeRange(from,dtLength)];

    NSData *imageData=nil;
    imageData = [NSData dataWithBytes:buffer length:dtLength];
    len=len-dtLength;
    from=from dtLength;
    NSLog(@"sending buffer=%s legth of buffer=%lli len value=%lli",buffer,dtLength,len);   //everything is fine till here
    NSMutableDictionary *projectDictionary3 = [NSMutableDictionary dictionaryWithCapacity:1];
    [projectDictionary3 setObject:@"2100" forKey:@"Action"];
    [projectDictionary3 setObject:[NSString stringWithFormat:@"%i",pktId] forKey:@"PacketId"];
    [projectDictionary3 setObject:@"101" forKey:@"FileAction"];
    if(imageData!=nil)
    [projectDictionary3 setObject: imageData forKey:@"FData"];//data
    [projectDictionary3 setObject:[NSString stringWithFormat:@"%i",(int)dtLength] forKey:@"DataLength"];//data
    NSError *jsonSerializationError = nil;
    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:projectDictionary3 options:NSJSONWritingPrettyPrinted error:amp;jsonSerializationError]; //"here crashed"
    if(!jsonSerializationError)
    {
        NSString *serJSON = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
        NSLog(@"Serialized JSON: %@", serJSON);
    }
    else
    {
     NSLog(@"JSON Encoding Failed: %@", [jsonSerializationError localizedDescription]);
    }
code to send over stream
[self sendDataToServer:jsonData];
  

} //цикл while

}

Вот задача. Если я отправляю простые данные (например, строку) с помощью этого кода, они успешно передаются на сервер (через сокет). Но когда я пытаюсь разбить фактическое изображение в формате jpeg на части и связать его в nsdictionary, чтобы создать json, он выходит из строя со следующей ошибкой.

завершение работы приложения из-за неперехваченного исключения ‘NSInvalidArgumentException’, причина: ‘Недопустимый тип при записи в формате JSON (NSConcreteData)’. Любая помощь здесь была бы высоко оценена.

РЕДАКТИРОВАТЬ: Как объяснил bobnoble, я понимаю причину исключения. Однако, в таком случае, как мне выполнить отправку данных на сервер

Комментарии:

1. Во-первых, почему вы разбиваете данные на фрагменты? Покажите код цикла. Во-вторых, вы не можете поместить необработанные данные в JSON, вам нужно преобразовать их в форму, поддерживаемую JSON, такую как строка Base64.

2. В порядке использования getBytes: и dataWithBytes просто используйте: subdataWithRange: . Но зачем разбивать данные?

3. Привет, Zaph, я обновил вопрос с более подробной информацией.

Ответ №1:

Удаление всех частей, кроме ключевых, которые необходимо изменить.
Как я уже говорил в комментариях, данные должны быть в формате, который обрабатывает JSON, необработанные байты неприемлемы, поэтому один из способов — закодировать данные с помощью Base64. Получателю также потребуется декодировать строку Base64 в данные.

 while (b) {
    //get chunk from and dtLength

    NSData *imageData = [dt subdataWithRange:NSMakeRange(from, dtLength)];
    NSData *imageBase64Data = [imageData base64EncodedDataWithOptions:0];
    NSString *imageBase64String = [[NSString alloc] initWithData:imageBase64Data encoding: NSUTF8StringEncoding];

    // update len and from

    NSLog(@"sending imageData =%@. dtLength =%i len =%lli", imageBase64String, dtLength, len);   

    // Create projectDictionary3 and add items

    // Added image data)
    if(imageData.length) {
        [projectDictionary3 setObject: imageBase64String forKey:@"FData"];
    }
    [projectDictionary3 setObject:@(imageBase64String.length) forKey:@"DataLength"];

    // serialize projectDictionary3 into JSON and sent to server];
}
  

Комментарии:

1. Привет, Zaph, теперь я сталкиваюсь с аварийным завершением приложения с новой ошибкой из-за неперехваченного исключения ‘NSInvalidArgumentException’, причина: ‘-[NSSubrangeData base64EncodedDataWithOptions:]: нераспознанный селектор, отправленный в instace

2. NSData *imageBase64Data = [ImageData base64EncodedDataWithOptions: 0]; приложение завершило работу в этой строке

3. Что было сообщением о сбое? Что такое ImageData? Какова была его длина? NSLog imageData

Ответ №2:

Из NSJSONSerialization ссылки на класс:

Объект, который может быть преобразован в JSON, должен обладать следующими свойствами:

  • Объектом верхнего уровня является NSArray или NSDictionary.
  • Все объекты являются экземплярами NSString, NSNumber, NSArray, NSDictionary или NSNull.
  • Все ключи словаря являются экземплярами NSString.
  • Числа не равны NaN или бесконечности.

Второй маркер не включает NSData , и именно поэтому генерируется исключение.

Преобразуйте данные изображения в кодировку Base64, затем поместите их в словарь как NSString . Взгляните на NSData base64EncodedStringWithOptions метод.

Комментарии:

1. Приношу свои извинения, я не очень хорошо объяснил первоначальный вопрос. Следовательно, я изменил его. Могу ли я, пожалуйста, попросить вас взглянуть на это и дать мне предложения.