Загрузка изображения на сервер Подробное объяснение для начинающих

Я работаю над загрузкой изображения на сервер за последние два дня, так как существует множество вопросов о загрузке изображения через AFNetworking и NSURLSession и других методах загрузки всего, что я спрашиваю, я не нашел ни одного ответа, объясняющего вся концепция о том, как все работает и что происходит под капотом, я искал на youtube, а также все материалы доступны в Swift и не доверяют мне вообще никаких объяснений, и по своему результату я обнаружил, что этот ответ кажется мне знакомым

    //Init the NSURLSession with a configuration
NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *defaultSession = [NSURLSession sessionWithConfiguration: defaultConfigObject delegate: nil delegateQueue: [NSOperationQueue mainQueue]];

//Create an URLRequest
NSURL *url = [NSURL URLWithString:@"yourURL"];
NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:url];

//Create POST Params and add it to HTTPBody
NSString *params = @"api_key=APIKEY&[email protected]&password=password";
[urlRequest setHTTPMethod:@"POST"];
[urlRequest setHTTPBody:[params dataUsingEncoding:NSUTF8StringEncoding]];

//Create task
NSURLSessionDataTask *dataTask = [defaultSession dataTaskWithRequest:urlRequest completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
    //Handle your response here
}];

[dataTask resume];

а также самый популярный ответ по этой теме от пользователяXJones является:-

Here's code from my app to post an image to our web server:

// Dictionary that holds post parameters. You can set your post parameters that your server accepts or programmed to accept.
NSMutableDictionary* _params = [[NSMutableDictionary alloc] init];
[_params setObject:[NSString stringWithString:@"1.0"] forKey:[NSString stringWithString:@"ver"]];
[_params setObject:[NSString stringWithString:@"en"] forKey:[NSString stringWithString:@"lan"]];
[_params setObject:[NSString stringWithFormat:@"%d", userId] forKey:[NSString stringWithString:@"userId"]];
[_params setObject:[NSString stringWithFormat:@"%@",title] forKey:[NSString stringWithString:@"title"]];

// the boundary string : a random string, that will not repeat in post data, to separate post data fields.
NSString *BoundaryConstant = [NSString stringWithString:@"----------V2ymHFg03ehbqgZCaKO6jy"];

// string constant for the post parameter 'file'. My server uses this name: `file`. Your's may differ 
NSString* FileParamConstant = [NSString stringWithString:@"file"];

// the server url to which the image (or the media) is uploaded. Use your server url here
NSURL* requestURL = [NSURL URLWithString:@""]; 

// create request
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];                                    
[request setCachePolicy:NSURLRequestReloadIgnoringLocalCacheData];
[request setHTTPShouldHandleCookies:NO];
[request setTimeoutInterval:30];
[request setHTTPMethod:@"POST"];

// set Content-Type in HTTP header
NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", BoundaryConstant];
[request setValue:contentType forHTTPHeaderField: @"Content-Type"];

// post body
NSMutableData *body = [NSMutableData data];

// add params (all params are strings)
for (NSString *param in _params) {
    [body appendData:[[NSString stringWithFormat:@"--%@\r\n", BoundaryConstant] dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n", param] dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[[NSString stringWithFormat:@"%@\r\n", [_params objectForKey:param]] dataUsingEncoding:NSUTF8StringEncoding]];
}

// add image data
NSData *imageData = UIImageJPEGRepresentation(imageToPost, 1.0);
if (imageData) {
    [body appendData:[[NSString stringWithFormat:@"--%@\r\n", BoundaryConstant] dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"image.jpg\"\r\n", FileParamConstant] dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[[NSString stringWithString:@"Content-Type: image/jpeg\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:imageData];
    [body appendData:[[NSString stringWithFormat:@"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
}

[body appendData:[[NSString stringWithFormat:@"--%@--\r\n", BoundaryConstant] dataUsingEncoding:NSUTF8StringEncoding]];

// setting the body of the post to the reqeust
[request setHTTPBody:body];

// set the content-length
NSString *postLength = [NSString stringWithFormat:@"%d", [body length]];
[request setValue:postLength forHTTPHeaderField:@"Content-Length"];

// set URL
[request setURL:requestURL];

Но моя мысль в том, что я учусь сам, и это очень трудно понять новичку без объяснения, поэтому все, что я прошу, это объяснение, подробное объяснение всего процесса, если кому-то трудно потратить на это вопрос, хотите верьте, хотите нет, но я нашел эту самую трудную тему до сих пор, потому что главная причина в том, что нет никаких учебных пособий по всему процессу, а также вообще нет объяснений для начинающих, если кто-то может сделать шаг сейчас и объяснить концепцию, это будет легче студентам, которые будут учиться завтра. Так что любой, кто может объяснить это подробно и как работает процесс загрузки и некоторые шаги для справки, будет принята с благодарностью.

Заметка : Посмотрим, у меня есть API и ключ "изображение".

Ответы на вопрос(3)

Я думаю, что это полезно для вас ...

- (void)sendImageToServer
{
    UIImage *yourImage= [UIImage imageNamed:@"image.png"];
    NSData *imageData = UIImagePNGRepresentation(yourImage);
    NSString *base64 = [imageData base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
    NSString *strImage = [NSString stringWithFormat:@"data:image/png;base64,%@",base64];

    NSMutableDictionary *dic = [[NSMutableDictionary alloc] initWithObjectsAndKeys:strImage,@"image", nil];
    NSError * err;
    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dic options:0 error:&err];
    NSString *UserProfileInRequest = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
    NSData *data=[UserProfileInRequest dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
    NSString *len = [NSString stringWithFormat:@"%ld", (unsigned long)[data length]];

    // Init the URLRequest

    NSMutableURLRequest *req = [[NSMutableURLRequest alloc] init];
    [req setURL:[NSURL URLWithString:@"http://YOUR_URL"]];
    [req setHTTPMethod:@"POST"];
    [req setValue:len forHTTPHeaderField:@"Content-Type"];
    [req setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
    [req setValue:@"application/json" forHTTPHeaderField:@"Accept"];
    [req setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
    [req setHTTPBody:data];

    NSURLSession *session = [NSURLSession sharedSession];
    [[session dataTaskWithRequest:req completionHandler:^(NSData *dt, NSURLResponse *response, NSError *err){
        //Response Data
        NSMutableDictionary *dic = [NSJSONSerialization JSONObjectWithData:dt options:kNilOptions error:&err];
        NSLog(@"%@", [dic description]);

    }]resume];
}
 dreamBegin29 июл. 2016 г., 10:09
Можете ли вы объяснить процесс построчно?
 Ravi Dhorajiya28 июл. 2016 г., 20:11
Хорошо, я отредактирую свой ответ завтра, тогда вы можете проверить мой ответ.
 dreamBegin28 июл. 2016 г., 20:06
эй, @Ravi, я ценю ваше время, но проблема в том, что у меня уже есть много решений, но без объяснения. Я хочу узнать весь процесс, например, сначала у нас есть изображение, преобразованное в nsdata, чем мы делаем запрос URL, а затем еще больше, и все эти дополнительные поля, такие как set-value, header и т. д. а также NSURLConnection устарела с NSURLSession
 dreamBegin28 июл. 2016 г., 20:12
Это было бы прекрасно : )
 dreamBegin29 июл. 2016 г., 11:14
это также показывает ошибку: - Ошибка домена = NSCocoaErrorDomain Code = 3840 «Нет значения». UserInfo = {NSDebugDescription = Нет значения.}
Решение Вопроса

здесь мы будем смотреть назагрузка изображений наряду с некоторыми ** параметрами, потому что большую часть времени мы загружаем изображение вместе с некоторыми параметрами, такими как userId.

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

-(void)callApiWithParameters:(NSDictionary *)inputParameter images:(NSArray *)i,mage  imageParamters:(NSArray *)FileParamConstant{

//1
   NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];

   [request setHTTPShouldHandleCookies:NO];
   [request setTimeoutInterval:30];
   [request setHTTPMethod:@"POST"];

//2
   NSString *boundary = @"------CLABoundaryGOKUL";

//3
   NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary];
   [request setValue:contentType forHTTPHeaderField: @"Content-Type"];

//4
   NSMutableData *body = [NSMutableData data];

   for (NSString *key in inputParameter) {

   [body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
   [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n", key] dataUsingEncoding:NSUTF8StringEncoding]];
   [body appendData:[[NSString stringWithFormat:@"%@\r\n", [inputParameter objectForKey:key]] dataUsingEncoding:NSUTF8StringEncoding]];
  }

   for (int i = 0; i < image.count; i++) {

      NSData *imageDatasss = UIImagePNGRepresentation(image[i]);

      if (imageDatasss)
      {
          [body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
          [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"image.jpg\"\r\n", FileParamConstant[i]] dataUsingEncoding:NSUTF8StringEncoding]];
          [body appendData:[@"Content-Type:image/jpeg\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
          [body appendData:imageDatasss];
          [body appendData:[[NSString stringWithFormat:@"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
     }
  }

  [body appendData:[[NSString stringWithFormat:@"--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];

//5
  [request setHTTPBody:body];

//6
  [request setURL:[NSURL URLWithString:@"http://changeThisWithYourbaseURL?"]];//Eg:@"http://dev1.com/PTA_dev/webservice/webservice.php?"

//7
  [NSURLConnection sendAsynchronousRequest:request
                               queue:[NSOperationQueue mainQueue]
                   completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {

                       NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)response;

                       //8
                       if ([httpResponse statusCode] == 200) {
                           NSDictionary * APIResult =[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
                           NSLog(@"Response of %@: %@",[inputParameter valueForKey:@"service"],APIResult);

                       }else{
                           //9
                           NSLog(@"%@",error.localizedDescription);
                       }
                   }];


 }

НОТА: Поскольку это широкая тема, я предоставил ссылку на документацию для получения подробной информации.

Мы используем ** NSMutableURLRequest ** вместо ** NSURLRequest **, потому что мы собираемся добавить к нему некоторые данные. Если вам нужно глубокое разъяснение по поводу изменяемого запроса URL, просмотрите этодокументация.setHTTPShouldHandleCookies здесь мы должны решить, будем ли мы использовать куки или нет. Чтобы узнать больше овизитsetTimeoutInterval Это помогает установить ограничение по времени для URL-запроса. Добавление временного интервала в секундах после заданного времени, запрос будет прекращен.setHTTPMethod имеютсямного методы. Но мы используемПОЛУЧИТЬ а такжеСООБЩЕНИЕ методы во многих случаях. Разница между POST и GET естьВот а такжеВотГраница помогает отделить параметры друг от друга, чтобы сервер мог их идентифицировать. Граница может быть любой, если вы захотите ее редактировать.Здесь мы используеммногочастному / форм-данных; граничные = как тип контента. Чтобы узнать, почему мы собираемся на этот тип контента, посмотрите наэтот нить.

NSMutableData * body мы собираемся добавить все параметры и значения к этим данным и позжеsetHTTPBody кURLRequest.

Если это то, как мы вызываем метод callApiWithParameters

 - (IBAction)Done:(id)sender{
        NSDictionary * inputParameters = [NSDictionary dictionaryWithObjectsAndKeys:
                      @"1",@"user_id" ,
                      "XXX",@"name" ,
                      nil];
         NSArray * image = [NSArray arrayWithObjects:[UIImage imageNamed:@"Test"],[UIImage imageNamed:@"Test1"],nil];
         NSArray * imageParameters = [NSArray arrayWithObjects:@"img_one",@"img_two",nil];
         [self callApiWithParameters:inputParameters images:image imageParamters:imageParameters];
  }

тогда данные (т.е. тело) будут выглядеть так

Content-Type=multipart/form-data; boundary=------CLABoundaryGOKUL

--------CLABoundaryGOKUL
Content-Disposition: form-data; name=user_id

1
--------CLABoundaryGOKUL
Content-Disposition: form-data; name=name

XXX
--------CLABoundaryGOKUL
Content-Disposition: form-data; name=img_one; filename=image.jpg

Content-Type:image/jpeg

//First image data appended here

--------CLABoundaryGOKUL
Content-Disposition: form-data; name=img_two; filename=image.jpg

Content-Type:image/jpeg

//Second image data appended here.

Приведенные выше данные четко объяснят, что происходит, все параметры и ключи были добавлены в данные.Вот Вы можете найти более подробную информацию об отправке multipart / формы.

Теперь просто добавьте вышеуказанные данные для запроса[request setHTTPBody:body];setURL в этом методе добавьте ваш базовый URL вашего приложения.Теперь все, что нам нужно сделать, это подключиться к серверу и отправить запрос. Здесь мы используем NSURLConnection для отправки запроса.Описание о NSURLConnection Загружает данные для запроса URL и выполняет блок обработчика в очереди операций, когда запрос завершается или завершается неудачно.

StatusCode что помогает выяснить, получили ли мы успешный ответ от сервера. Если200 значит ок,500 означает «Внутренняя ошибка сервера» и т. д. подробнееВот .

Обработайте ошибку в другом случае.

FYI Я объяснил, что я могу, ссылки для лучшего понимания.

РЕДАКТИРОВАТЬ:

Просто измените имя вimageParamater массив, чтобы удовлетворить ваши требования измененыimg_one & img_two собраз.

 - (IBAction)Done:(id)sender{
     //Change input parameters as per your requirement.
     NSDictionary * inputParameters = [NSDictionary dictionaryWithObjectsAndKeys:
                                  @"1",@"user_id" ,
                                  "XXX",@"name" ,
                                  nil];
    NSArray * image = [NSArray arrayWithObjects:[UIImage imageNamed:@"Test"],nil]; //Change Test with your image name
    NSArray * imageParameters = [NSArray arrayWithObjects:@"image",nil];//Added image as a key.
    [self callApiWithParameters:inputParameters images:image imageParamters:imageParameters];
              }

и измените точку 6 с вашим примером базового URL,

// 6

 [request setURL:[NSURL URLWithString:@"http://google.com/files/upload.php?"]];
 dreamBegin01 авг. 2016 г., 13:22
Правильный..........
 Gokul01 авг. 2016 г., 12:13
@dreamBegin спасибо
 dreamBegin01 авг. 2016 г., 14:01
Большое спасибо, я посмотрю на это глубже.
 dreamBegin01 авг. 2016 г., 13:00
эй подумал, у меня есть ключ "Изображение" и API, например "google.com/files/upload.php«Какие необходимые изменения мне нужно внести в этот вопрос, чтобы получить перестановку? Если вы загрузите другой ответ в соответствии с требованием, которое я задаю, это было бы очень полезно, заранее спасибо.
 Gokul01 авг. 2016 г., 13:12
Вам нужно загрузить изображение в APIgoogle.com/files/upload.php с ключомобраз право..?
 dreamBegin01 авг. 2016 г., 12:04
Отлично Это то, что я ищу, Цените ваши усилия, брат.
 Gokul01 авг. 2016 г., 13:51
 Gokul01 авг. 2016 г., 13:39
проверьте отредактированный ответ, он может удовлетворить ваши требования.

Используйте AFNetworking Для этой задачи, которая даст очень простое и надежное решение.

Ваш ответ на вопрос