Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>There is an issue with your Objective-C code, in which you define your <code>Content-Type</code> header as <code>application/x-www-form-urlencoded</code>, but then the body of the request is not consistent with that <code>Content-Type</code>. You can, theoretically, write PHP code that handles the request as constructed (read the raw data of the body), but it's probably better to change the request to conform to established standards.</p> <p>If you write the code to construct such a request yourself, it's a little ugly (see the end of this answer), so I'd suggest using <a href="https://github.com/AFNetworking/AFNetworking" rel="nofollow">AFNetworking</a>, which greatly simplifies the creation of such requests:</p> <pre><code>NSData *zipData = [NSData dataWithContentsOfFile:zipFile]; AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager]; [manager POST:urlString parameters:nil constructingBodyWithBlock:^(id&lt;AFMultipartFormData&gt; formData) { [formData appendPartWithFileData:zipData name:@"file" fileName:[zipFile lastPathComponent] mimeType:@"application/zip"]; } success:^(AFHTTPRequestOperation *operation, id responseObject) { BOOL success = [responseObject[@"success"] boolValue]; NSString *errorMessage = responseObject[@"error"]; NSLog(@"Success: %d; Error message: %@", success, errorMessage); } failure:^(AFHTTPRequestOperation *operation, NSError *error) { NSLog(@"Error: %@", error); }]; </code></pre> <p>Note, this expects a JSON response, so the corresponding PHP code to receive it, save it into an "upload" subdirectory, and return JSON response might look like:</p> <pre><code>&lt;?php header("Content-Type: application/json"); $allowedExts = array("zip", "gz"); $extension = end(explode(".", $_FILES["file"]["name"])); if (in_array($extension, $allowedExts)) { if ($_FILES["file"]["error"] &gt; 0) { echo json_encode(array("success" =&gt; false, "error" =&gt; $_FILES["file"]["error"])); } else { if (file_exists("upload/" . $_FILES["file"]["name"])) { echo json_encode(array("success" =&gt; false, "error" =&gt; $_FILES["file"]["name"] . " already exists")); } else { move_uploaded_file($_FILES["file"]["tmp_name"], "upload/" . $_FILES["file"]["name"]); echo json_encode(array("success" =&gt; true)); } } } else { echo json_encode(array("success" =&gt; false, "error" =&gt; "Invalid file type")); } ?&gt; </code></pre> <hr> <p>While I'd really encourage you to use AFNetworking, if you want to construct your own request, you could do something like:</p> <pre><code>[self uploadFileAtPath:zipFile forField:@"file" URL:[NSURL URLWithString:urlString] parameters:nil completion:^(BOOL success, NSString *errorMessage) { NSLog(@"success = %d; errorMessage = %@", success, errorMessage); }]; </code></pre> <p>Where, <code>uploadFileAtPath</code> and some supporting methods are defined like so:</p> <pre><code>- (void)uploadFileAtPath:(NSString *)path forField:(NSString *)fieldName URL:(NSURL*)url parameters:(NSDictionary *)parameters completion:(void (^)(BOOL success, NSString *errorMessage))completion { NSString *filename = [path lastPathComponent]; NSData *data = [NSData dataWithContentsOfFile:path]; NSMutableData *httpBody = [NSMutableData data]; NSString *boundary = [self generateBoundaryString]; NSString *mimetype = [self mimeTypeForPath:path]; // configure the request NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url]; [request setCachePolicy:NSURLRequestReloadIgnoringLocalCacheData]; [request setHTTPShouldHandleCookies:NO]; [request setTimeoutInterval:30]; [request setHTTPMethod:@"POST"]; // set content type NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary]; [request setValue:contentType forHTTPHeaderField: @"Content-Type"]; // 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 if (data) { [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]]; // setting the body of the post to the reqeust [request setHTTPBody:httpBody]; [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) { if (connectionError) { if (completion) completion(FALSE, [NSString stringWithFormat:@"%s: sendAsynchronousRequest error: %@", __FUNCTION__, connectionError]); return; } NSError *error = nil; NSDictionary *responseObject = [NSJSONSerialization JSONObjectWithData:data options:0 error:&amp;error]; if (!responseObject) { if (completion) completion(FALSE, [NSString stringWithFormat:@"%s: JSONObjectWithData error=%@", __FUNCTION__, error]); return; } BOOL success = [responseObject[@"success"] boolValue]; NSString *errorMessage = responseObject[@"error"]; if (completion) completion(success, errorMessage); }]; } - (NSString *)generateBoundaryString { // generate boundary string // // adapted from http://developer.apple.com/library/ios/#samplecode/SimpleURLConnections // // Note in iOS 6 and later, you can just: // // return [NSString stringWithFormat:@"Boundary-%@", [[NSUUID UUID] UUIDString]]; CFUUIDRef uuid; NSString *uuidStr; uuid = CFUUIDCreate(NULL); assert(uuid != NULL); uuidStr = CFBridgingRelease(CFUUIDCreateString(NULL, uuid)); assert(uuidStr != NULL); CFRelease(uuid); return [NSString stringWithFormat:@"Boundary-%@", uuidStr]; } - (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; } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload