Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS, upload file with multipartform-data

I would like to upload file to HTTP server. I do it like that right now:

NSString *boundary = @"*****";

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

[request setURL:[NSURL URLWithString:@"http://someUploadScript.php"]];
[request setHTTPMethod:@"POST"];

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

[request setValue:@"Keep-Alive" forHTTPHeaderField: @"Connection"];

dispatch_async(queue, ^{
    NSMutableData *postbody = [NSMutableData data];

    [postbody appendData:[[NSString stringWithFormat:@"--%@\r\n",boundary] dataUsingEncoding:NSUTF8StringEncoding]];
    [postbody appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"userfile\"; filename=\"video.mp4\"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
    [postbody appendData:[@"Content-Type: application/octet-stream\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]];

    NSString* outputPath = @"somePathToFile";
    NSData *data = [NSData dataWithContentsOfFile:outputPath];

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

    [request setHTTPBody:postbody];
    previousBytesWritten = 0;
    connection = [[NSURLConnection alloc]initWithRequest:request delegate:self];
});

I would like to send some additional data in eg. filed "user" with "userId" value. I would like to send some kind of array like:

video[user] = "userId"
video[file] = //file bytes

I know I can do like this using HTTP multipartform-data but I really don know how and I don't understand how it works. Can some one explain me how can I do that and how it works?

like image 840
AYMADA Avatar asked Dec 28 '25 10:12

AYMADA


2 Answers

Try something like this:

NSMutableData *postbody = [NSMutableData data];

[postbody appendData:[[NSString stringWithFormat:@"--%@\r\n",boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[postbody appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"userfile\"; filename=\"video.mp4\"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
[postbody appendData:[@"Content-Type: application/octet-stream\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]];

NSString* outputPath = @"somePathToFile";
NSData *data = [NSData dataWithContentsOfFile:outputPath];

[postbody appendData:data];
[postbody appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];

// Adding one more field:
// append boundary
[postbody appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
// setting up form-data header, if it is text no 'filename' needed
[postbody appendData:[@"Content-Disposition: form-data; name=\"userId\"\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
// appending userId value
[postbody appendData:[_userId dataUsingEncoding:NSUTF8StringEncoding]];

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

[request setHTTPBody:postbody];

Also dont forget to add 'Content-Length' http header field in your request.

like image 127
Shmatlay Andrey Avatar answered Dec 30 '25 22:12

Shmatlay Andrey


AFNetowrking is Handy solution for today. Can achieve this easily.

For iOS 6 and above

AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
NSDictionary *parameters = @{@"foo": @"bar"};
NSURL *filePath = [NSURL fileURLWithPath:@"file://path/to/image.png"];
[manager POST:@"http://example.com/resources.json" parameters:parameters constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
    [formData appendPartWithFileURL:filePath name:@"image" error:nil];
} success:^(AFHTTPRequestOperation *operation, id responseObject) {
    NSLog(@"Success: %@", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
    NSLog(@"Error: %@", error);
}];

If project is to iOS 7 and above better to use.

NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer] multipartFormRequestWithMethod:@"POST" URLString:@"http://example.com/upload" parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
        [formData appendPartWithFileURL:[NSURL fileURLWithPath:@"file://path/to/image.jpg"] name:@"file" fileName:@"filename.jpg" mimeType:@"image/jpeg" 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(@"%@ %@", response, responseObject);
    }
}];

[uploadTask resume];

above code samples are from the library documentation. Which can be found at https://github.com/AFNetworking/AFNetworking

like image 26
MadNik Avatar answered Dec 30 '25 23:12

MadNik



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!