wake-up-neo.net

POST Multipart/Formulardaten mit Objective-C

Dieser HTML-Code übermittelt also die Daten im richtigen Format für mich.

<form action="https://www.example.com/register.php" method="post" enctype="multipart/form-data">
    Name: <input type="text" name="userName"><BR />
    Email: <input type="text" name="userEmail"><BR />
    Password: <input type="text" name="userPassword"><BR />
    Avatar: <input type="file" name="avatar"><BR />
    <input type="submit">
</form>

Ich habe eine ganze Reihe von Artikeln zum Thema Mehrteil-/Formulardaten POST unter iOS durchgesehen, aber keiner erklärt, was zu tun ist, wenn normale Parameter sowie der Dateiupload vorhanden sind.

Könnten Sie mir bitte mit dem Code zu POST in Obj-C helfen?

Vielen Dank!

57
Ali Almohsen

Der Prozess ist wie folgt:

  1. Erstellen Sie ein Wörterbuch mit den Parametern userName, userEmail und userPassword.

    NSDictionary *params = @{@"userName"     : @"rob",
                             @"userEmail"    : @"[email protected]",
                             @"userPassword" : @"password"};
    
  2. Bestimmen Sie den Pfad für das Bild:

    NSString *path = [[NSBundle mainBundle] pathForResource:@"avatar" ofType:@"png"];
    
  3. Erstellen Sie die Anfrage:

    NSString *boundary = [self generateBoundaryString];
    
    // configure the request
    
    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
    [request setHTTPMethod:@"POST"];
    
    // set content type
    
    NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary];
    [request setValue:contentType forHTTPHeaderField: @"Content-Type"];
    
    // create body
    
    NSData *httpBody = [self createBodyWithBoundary:boundary parameters:params paths:@[path] fieldName:fieldName];
    
  4. Dies ist die Methode, die oben zum Erstellen des Hauptteils der Anforderung verwendet wurde:

    - (NSData *)createBodyWithBoundary:(NSString *)boundary
                            parameters:(NSDictionary *)parameters
                                 paths:(NSArray *)paths
                             fieldName:(NSString *)fieldName {
        NSMutableData *httpBody = [NSMutableData data];
    
        // add params (all params are strings)
    
        [parameters enumerateKeysAndObjectsUsingBlock:^(NSString *parameterKey, NSString *parameterValue, BOOL *stop) {
            [httpBody appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
            [httpBody appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n", parameterKey] dataUsingEncoding:NSUTF8StringEncoding]];
            [httpBody appendData:[[NSString stringWithFormat:@"%@\r\n", parameterValue] dataUsingEncoding:NSUTF8StringEncoding]];
        }];
    
        // add image data
    
        for (NSString *path in paths) {
            NSString *filename  = [path lastPathComponent];
            NSData   *data      = [NSData dataWithContentsOfFile:path];
            NSString *mimetype  = [self mimeTypeForPath:path];
    
            [httpBody appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
            [httpBody appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"%@\"\r\n", fieldName, filename] dataUsingEncoding:NSUTF8StringEncoding]];
            [httpBody appendData:[[NSString stringWithFormat:@"Content-Type: %@\r\n\r\n", mimetype] dataUsingEncoding:NSUTF8StringEncoding]];
            [httpBody appendData:data];
            [httpBody appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
        }
    
        [httpBody appendData:[[NSString stringWithFormat:@"--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
    
        return httpBody;
    }
    
  5. Das Obige verwendet die folgenden Dienstmethoden:

    @import MobileCoreServices;    // only needed in iOS
    
    - (NSString *)mimeTypeForPath:(NSString *)path {
        // get a mime type for an extension using MobileCoreServices.framework
    
        CFStringRef extension = (__bridge CFStringRef)[path pathExtension];
        CFStringRef UTI = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, extension, NULL);
        assert(UTI != NULL);
    
        NSString *mimetype = CFBridgingRelease(UTTypeCopyPreferredTagWithClass(UTI, kUTTagClassMIMEType));
        assert(mimetype != NULL);
    
        CFRelease(UTI);
    
        return mimetype;
    }
    
    - (NSString *)generateBoundaryString {
        return [NSString stringWithFormat:@"Boundary-%@", [[NSUUID UUID] UUIDString]];
    }
    
  6. Dann senden Sie die Anfrage. Hier gibt es viele, viele Möglichkeiten.

    Wenn Sie beispielsweise NSURLSession verwenden, können Sie NSURLSessionUploadTask erstellen:

    NSURLSession *session = [NSURLSession sharedSession];  // use sharedSession or create your own
    
    NSURLSessionTask *task = [session uploadTaskWithRequest:request fromData:httpBody completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        if (error) {
            NSLog(@"error = %@", error);
            return;
        }
    
        NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
        NSLog(@"result = %@", result);
    }];
    [task resume];
    

    Oder Sie könnten eine NSURLSessionDataTask erstellen:

    request.HTTPBody = httpBody;
    
    NSURLSessionTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        if (error) {
            NSLog(@"error = %@", error);
            return;
        }
    
        NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
        NSLog(@"result = %@", result);
    }];
    [task resume];
    

    Das Obige setzt voraus, dass der Server nur eine Textantwort zurückgibt. Es ist besser, wenn der Server JSON zurückgegeben hat. In diesem Fall würden Sie NSJSONSerialization anstelle der NSString-Methode initWithData verwenden.

    Ebenso verwende ich die Vollendungsblock-Wiedergaben von NSURLSession, aber Sie können auch die reicheren Delegaten-basierten Wiedergaben verwenden. Aber das scheint über den Rahmen dieser Frage hinauszugehen, also überlasse ich es Ihnen.

Aber hoffentlich illustriert das die Idee.


Ich wäre nachlässig, wenn ich nicht darauf hinweisen würde, viel einfacher als oben, Sie können AFNetworking verwenden und die Schritte 1 und 2 oben wiederholen, aber dann einfach anrufen

AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
manager.responseSerializer = [AFHTTPResponseSerializer serializer]; // only needed if the server is not returning JSON; if web service returns JSON, remove this line
NSURLSessionTask *task = [manager POST:urlString parameters:params constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
    NSError *error;
    if (![formData appendPartWithFileURL:[NSURL fileURLWithPath:path] name:@"avatar" fileName:[path lastPathComponent] mimeType:@"image/png" error:&error]) {
        NSLog(@"error appending part: %@", error);
    }
}  progress:nil success:^(NSURLSessionTask *task, id responseObject) {
    NSLog(@"responseObject = %@", responseObject);
} failure:^(NSURLSessionTask *task, NSError *error) {
    NSLog(@"error = %@", error);
}];

if (!task) {
    NSLog(@"Creation of task failed.");
}
164
Rob

POST mehrere Bilder mit Multipart- oder Formulardaten mit Objective-C

-(void)multipleimageandstring
{
    NSString *[email protected]"URL NAME";

    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init] ;
    [request setURL:[NSURL URLWithString:urlString]];
    [request setHTTPMethod:@"POST"];

    NSMutableData *body = [NSMutableData data];

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

    // file
    float low_bound = 0;
    float high_bound =5000;
    float rndValue = (((float)arc4random()/0x100000000)*(high_bound-low_bound)+low_bound);//image1
    int intRndValue = (int)(rndValue + 0.5);
   NSString *str_image1 = [@(intRndValue) stringValue];

    UIImage *chosenImage1=[UIImage imageNamed:@"Purchase_GUI_curves-12 copy.png"];

    NSData *imageData = UIImageJPEGRepresentation(chosenImage1, 90);
    [body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"files\"; filename=\"%@.png\"\r\n",str_image1] dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[@"Content-Type: application/octet-stream\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[NSData dataWithData:imageData]];
    [body appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];





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

    [body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"apipassword\"\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[[NSString stringWithString:app.password] dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];

    [body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"adminId\"\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[[NSString stringWithString:app.adminId] dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];

    // close form
    [body appendData:[[NSString stringWithFormat:@"--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
    // set request body
    [request setHTTPBody:body];

    //return and test
    NSData *returnData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
    NSString *returnString = [[NSString alloc] initWithData:returnData encoding:NSUTF8StringEncoding];

    NSLog(@"%@", returnString);

}
2
manish gaurav

Versuchen Sie, dies für Video- und Bilddaten mit verschiedenen MIME-Typen zu verwenden.

NSDictionary *param;

AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];

// 1. Create `AFHTTPRequestSerializer` which will create your request.
AFHTTPRequestSerializer *serializer = [AFHTTPRequestSerializer serializer];
NSMutableURLRequest *request;

NSData *fileData;
if ([objDoc.url containsString:@".mp4"]) {
    manager.responseSerializer.acceptableContentTypes = [manager.responseSerializer.acceptableContentTypes setByAddingObject:@"application/json"];
    [serializer setValue:@"video/mp4" forHTTPHeaderField:@"Content-Type"];
    manager.requestSerializer = serializer;
}

// 2. Create an `NSMutableURLRequest`.

NSLog(@"filename =%@",objDoc.url);
request= [serializer multipartFormRequestWithMethod:@"POST" URLString:strUrl parameters:param constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {

    if ([objDoc.url containsString:@".mp4"]) {
        [formData appendPartWithFileData:fileData
                                    name:@"File"
                                fileName:@"video.mp4"
                                mimeType:@"video/mp4"];

    }else{
        [formData appendPartWithFileData:fileData
                                    name:@"File"
                                fileName:@"image.jpeg"
                                mimeType:@"image/jpeg"];
    }

} error:nil];

// 3. Create and use `AFHTTPRequestOperationManager` to create an `AFHTTPRequestOperation` from the `NSMutableURLRequest` that we just created.

self.objeDocument.isUploading = [NSNumber numberWithInt:1];

self.operation = [manager HTTPRequestOperationWithRequest:request
                                                  success:^(AFHTTPRequestOperation *operation, id responseObject) {

                                                      NSLog(@"Success %@", responseObject);
                                                  } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
                                                      UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"Error!" message:@"The document attached has failed to upload." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
                                                      [alert show];
                                                      [self.operation cancel];
                                                      NSLog(@"Failure %@", error.description);
                                                  }];


// 4. Set the progress block of the operation.
[self.operation setUploadProgressBlock:^(NSUInteger __unused bytesWritten,
                                         long long totalBytesWritten,
                                         long long totalBytesExpectedToWrite) {
    NSLog(@"Wrote %lld/%lld", totalBytesWritten, totalBytesExpectedToWrite);
    float progress = (float)totalBytesWritten/(float)totalBytesExpectedToWrite;


}];

// 5. Begin!
[self.operation start];
1
Arvind Patidar

Versuche dies:

Swift 5

private func buildMultipartDataRequest(_ request: NetworkRequest, baseURL: NetworkEndPoint) -> URLRequest? {
  var returnRequest: NSMutableURLRequest?

  if let data = request.multipartData,
    let mimeType = request.mimeType,
    let fileName = request.fileName {

    var requestPath = request.endPoint.value
    if let urlParameters = request.urlParameters {
      requestPath += urlParameters.requestString()
    }

    let completePath = String(format: "%@%@", baseURL.value, requestPath)

    if let cleanPath = completePath.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed),
      let url = URL(string: cleanPath) {

      returnRequest = NSMutableURLRequest(url: url)
      returnRequest?.httpMethod = request.HTTPMethod.rawValue

      var allheaders: [String: String] = [ :]
      if let headers = request.headers {
        allheaders = headers
      }

      returnRequest?.allHTTPHeaderFields = allheaders

      let boundary = boundaryString()
      returnRequest?.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")

      let encoding: UInt = String.Encoding.utf8.rawValue

      if let boundaryStartData = "--\(boundary)\r\n".data(using: String.Encoding(rawValue: encoding)),
        let fileNameData = "Content-Disposition:form-data; name=\"picture\"; filename=\"\(fileName)\"\r\n".data(using: String.Encoding(rawValue: encoding)),
        let contentTypeData = "Content-Type: \(mimeType)\r\n\r\n".data(using: String.Encoding(rawValue: encoding)),
        let endLineData = "\r\n".data(using: String.Encoding(rawValue: encoding)),
        let boundaryEndData = "--\(boundary)--\r\n".data(using: String.Encoding(rawValue: encoding)) {

        let body = NSMutableData()

        if let bodyParameters = request.bodyParameters as? [String: AnyObject] {
          bodyParameters.forEach { (pair) in
            if let key = "Content-Disposition: form-data; name=\"\(pair.key)\"\r\n\r\n".data(using: String.Encoding(rawValue: encoding)),
              let value = "\(pair.value)\r\n".data(using: String.Encoding(rawValue: encoding)) {
                body.append(boundaryStartData)
                body.append(key)
                body.append(value)
            }
          }
        }

        body.append(boundaryStartData)
        body.append(fileNameData)

        body.append(contentTypeData)
        body.append(data)
        body.append(endLineData)
        body.append(boundaryEndData)

        returnRequest?.httpBody = body as Data
      }
    }
  }

   return returnRequest as URLRequest?
 }

where NetworkRequest - Einfaches Protokoll, das Anforderungsinformationen enthält

protocol NetworkRequest: class {

  var HTTPMethod: NetworkRequestType { get }

  var endPoint: NetworkEndPoint { get }

  var urlParameters: [String: AnyObject]? { get }

  var bodyParameters: AnyObject? { get }

  var headers: [String: String]? { get }

  var multipartData: Data? { get }

  var mimeType: NetworkMimeType? { get }

  var fileName: String? { get }
}

NetworkEndPoint - Endpunktwert

struct NetworkEndPoint {

  let value: String
}

Grenzstich

private func boundaryString() -> String {
  return "Boundary-\(UUID().uuidString)"
}

NetworkRequestType:

enum NetworkRequestType: String {

  case UNKNOWN

  case POST
  case GET
  case PUT
  case DELETE
  case PATCH
  // ....
}

NetworkMimeType

enum NetworkMimeType: String {

  case html, htm, shtml = "text/html"
  case css = "text/css"
  case xml = "text/xml"
  case gif = "image/gif"
  case jpeg, jpg = "image/jpeg"
  case jScript = "application/javascript"
  case atom = "application/atom+xml"
  case rss = "application/rss+xml"
  case mml = "text/mathml"
  case txt = "text/plain"
  case jad = "text/vnd.Sun.j2me.app-descriptor"
  case wml = "text/vnd.wap.wml"
  case htc = "text/x-component"
  case png = "image/png"
  case tiff, tif = "image/tiff"
  case wbmp = "image/vnd.wap.wbmp"
  case ico = "image/x-icon"
  case jng = "image/x-jng"
  case bmp = "image/x-ms-bmp"
  case svg, svgz = "image/svg+xml"
  case webp = "image/webp"
  case woff = "application/font-woff"
  case jar, war, ear = "application/Java-archive"
  case json = "application/json"
  case hqx = "application/mac-binhex40"
  case doc = "application/msword"
  case pdf = "application/pdf"
  case postscript, eps, aiPostscript = "application/postscript"
  case rtf = "application/rtf"
  case m3u8 = "application/vnd.Apple.mpegurl"
  case xls = "application/vnd.ms-Excel"
  case eot = "application/vnd.ms-fontobject"
  case ppt = "application/vnd.ms-PowerPoint"
  case wmlc = "application/vnd.wap.wmlc"
  case kml = "application/vnd.google-earth.kml+xml"
  case kmz = "application/vnd.google-earth.kmz"
  case sevenZ = "application/x-7z-compressed"
  case cco = "application/x-cocoa"
  case jardiff = "application/x-Java-archive-diff"
  case jnlp = "application/x-Java-jnlp-file"
  case run = "application/x-makeself"
  case Perl, perlm = "application/x-Perl"
  case prc, pdb = "application/x-pilot"
  case rar = "application/x-rar-compressed"
  case rpm = "application/x-redhat-package-manager"
  case sea = "application/x-sea"
  case swf = "application/x-shockwave-flash"
  case sit = "application/x-stuffit"
  case tcl = "application/x-tcl"
  case der, pem, crt = "application/x-x509-ca-cert"
  case xpi = "application/x-xpinstall"
  case xhtml = "application/xhtml+xml"
  case xspf = "application/xspf+xml"
  case Zip = "application/Zip"
  case bin, exe, dll, deb, dmg, iso, img, msi, msp, msm = "application/octet-stream"
  case docx = "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
  case xlsx = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
  case pptx = "application/vnd.openxmlformats-officedocument.presentationml.presentation"
  case mid, midi, kar = "audio/midi"
  case mp3 = "audio/mpeg"
  case ogg = "audio/ogg"
  case m4a = "audio/x-m4a"
  case realAudio = "audio/x-realaudio"
  case threegpp, threegp = "video/3gpp"
  case mpts = "video/mp2t"
  case mp4 = "video/mp4"
  case mpeg, mpg = "video/mpeg"
  case mov = "video/quicktime"
  case webm = "video/webm"
  case flv = "video/x-flv"
  case m4v = "video/x-m4v"
  case mng = "video/x-mng"
  case asx, asf = "video/x-ms-asf"
  case wmv = "video/x-ms-wmv"
  case avi = "video/x-msvideo"
}
0
gbk

Ich habe einige Zeit damit zu kämpfen gehabt. Wenn Sie mehrere Bilder oder andere Dateitypen hochladen möchten, können Sie Folgendes tun, indem Sie AFNetworking 3.0 verwenden.

NSDictionary *params = @{key        : value,
                            ..... etc
                         };

 NSString *urlString = @"http://..... your endpoint url";

AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
manager.responseSerializer = [AFHTTPResponseSerializer serializer]; // only needed if the server is not returning JSON;  

NSURLSessionTask *task = [manager POST:urlString parameters:params constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
    for (int x = 0 ; x< contentArray.count; x++) {
        AttachmentsModel *model = contentArray[x];

        if(model.type == ImageAttachmentType){
            [formData appendPartWithFileData:model.data name:model.name fileName:model.fileName mimeType:model.mimeType];

        }else if(model.type == AudioAttachmentType){
            NSURL *urlVideoFile = [NSURL fileURLWithPath:model.path];
            [formData appendPartWithFileURL:urlVideoFile name:model.name fileName:model.fileName mimeType:model.mimeType error:nil];
        }else{
            [formData appendPartWithFileURL:model.url name:model.name fileName:model.fileName mimeType:model.mimeType error:nil];

        }

    }
}  progress:nil success:^(NSURLSessionTask *task, id responseObject) {
    [Utility stopLoading];

     NSString *result = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];
    NSLog(@"result = %@", result);

    id json = [NSJSONSerialization JSONObjectWithData:responseObject options:0 error:nil];


    if (block) {

        //your response comes here
    }

} failure:^(NSURLSessionTask *task, NSError *error) {
    NSLog(@"error = %@", error);

}];

if (!task) {
    NSLog(@"Creation of task failed.");
}

Und so sieht mein AttachmentsModel aus:

//  AttachmentsModel.h

typedef enum AttachmnetType{
    ImageAttachmentType,
    AudioAttachmentType,
    VideoAttachmentType
} AttachmnetType;

@interface AttachmentsModel : NSObject

@property (strong, nonatomic) NSString *path;
@property (strong, nonatomic) NSData *data;
@property (strong, nonatomic) NSString *mimeType;
@property (strong, nonatomic) NSString *name;
@property (strong, nonatomic) NSString *fileName;
@property (strong, nonatomic) NSURL *url;
0
Mutawe