4

I'm using AFNetworking to try to upload a file:

-(void)uploadFile{

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *filePath = [documentsDirectory stringByAppendingPathComponent:@"data.sqlite"];
    NSURL *filePathURL = [NSURL fileURLWithPath:filePath];

    NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer] multipartFormRequestWithMethod:@"POST" URLString:@"http://localhost:8888/myApp/upload.php" parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
        [formData appendPartWithFileURL:filePathURL name:@"file" fileName:@"data.sqlite" mimeType:@"text/html" error:nil];
    } error:nil];

    AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
    NSProgress *progress = nil;

    NSURLSessionUploadTask *uploadTask = [manager uploadTaskWithStreamedRequest:request progress:&progress completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
        if (error) {
            NSLog(@"Error: %@", error);
        } else {
            NSLog(@"Success: %@ %@", response, responseObject);
        }
    }];

    [uploadTask resume];
}

And this php file upload.php:

<?php

    $uploaddir = 'uploads/';
    $file = basename($_FILES['uploadedfile']['name']);
    $uploadfile = $uploaddir . $file;

    echo "file=".$file;

    if (move_uploaded_file($_FILES['uploadedfile']['tmp_name'], $uploadfile)) {
        echo $file;
    }
    else {
        echo "error";
    }
    ?>

It's printing:

Error Domain=com.alamofire.error.serialization.response Code=-1016 "Request failed: unacceptable content-type: text/html" UserInfo=0x7b8b2bf0

Is the problem from the mimeType ? I also used application/x-sqlite3 content type in both iOS and php sides.

androniennn
  • 3,117
  • 11
  • 50
  • 107
  • You need a valid enctype when uploading files. – Funk Forty Niner Dec 24 '14 at 14:23
  • @Fred-ii- What could be "valid" in my case ? – androniennn Dec 24 '14 at 14:29
  • I did notice you're using `AFMultipartFormData` however the `text/html` is the part that perplexes me. Usually a multi-part is what's used, but in your case, I'd try replacing `text/html` with `text/plain` try that and see what it says. – Funk Forty Niner Dec 24 '14 at 14:33
  • @Fred-ii- I already tested with `text/plain` but same problem. – androniennn Dec 24 '14 at 14:42
  • @Rob You have reason, my bad, I replaced `file` with `uploadedFile` and changed the content type to `application/x-sqlite3`, the file UPLOADS but I don't know why it's showing the error `"Request failed: unacceptable content-type: application/x-sqlite3"` – androniennn Dec 24 '14 at 14:48
  • 1
    Try `application/octet-stream` which is the fallback mime type for unknown binary streams. As RFC 2388 says, "As with all multipart MIME types, each part has an optional 'Content-Type', which defaults to text/plain. If the contents of a file are returned via filling out a form, then the file input is identified as the appropriate media type, if known, or 'application/octet-stream'." – Rob Dec 24 '14 at 14:49
  • See if these Q&A's will help http://stackoverflow.com/q/19114623/ – Funk Forty Niner Dec 24 '14 at 14:53
  • 1
    I'd also suggest supplying an `error` parameter to `multipartFormRequestWithMethod`. By the way, see my updated answer re `responseSerializer`. – Rob Dec 24 '14 at 14:55
  • 1
    You say "I also used `application/x-sqlite3` content type in both iOS and php sides." What do you mean by "php side"? The `header()` call?!? The `application/x-sqlite3` would be inappropriate there. There are two completely different `Content-Type` settings. One is the mime-type for the part of the multipart request in your client code (which should be `application/octet-stream` or `application/x-sqlite3`). The other is the header of the response in your PHP code (which should be `text/plain` for the current PHP code, or if you change PHP code to return JSON, it would be `application/json`). – Rob Dec 24 '14 at 15:00
  • 1
    @Rob: A very explained comments, perfect ! So the client part (iOS) is sending an sqlite file, so the mimeType would be `application/octet-stream` or `application/x-sqlite3`, and for the server side is returning in my case a plain text so the `content-type` would be `text/plain`. – androniennn Dec 24 '14 at 15:05

1 Answers1

6

The client-side code is uploading using the file field name, but the server code is looking for uploadedfile. You have to use the same field name on both platforms.

The mime type should be fixed. Because SQLite files are binary files, not text files, I'd suggest a mime type of application/x-sqlite3 or application/octet-stream, rather than text/html or text/plain. But the mismatched field name is the more egregious issue.


By the way, you report an error message:

Error Domain=com.alamofire.error.serialization.response Code=-1016 "Request failed: unacceptable content-type: text/html" UserInfo=0x7b8b2bf0

This is generally a result that your server page is returning text/html, but AFURLSessionManager is expecting JSON.

You can change the manager's responseSerializer:

manager.responseSerializer = [AFHTTPResponseSerializer serializer];

Or, better, change your server code to return JSON.

Rob
  • 415,655
  • 72
  • 787
  • 1,044
  • 1
    *"Because SQLite files are binary files, not text files"* - Ah, I didn't know that till now. I didn't mean to give bad info to the OP earlier about changing it to `text/plain`, my mistake. I'll remember that one. – Funk Forty Niner Dec 24 '14 at 15:02
  • Thank you very much Rob, you're always here for helping us. I have now a `success` response, and that's completely logic. Thank you and accepted ! – androniennn Dec 24 '14 at 15:06