Search code examples
iosobjective-conedriveonenote

How to upload multiple image in single OneNote page?


I am creating OneNote page using OneDrive iOS SDK from my iOS application. This is the code i did for post request for multiple image.

NSMutableArray *selecedFileNames = [[NSMutableArray alloc] init];
NSString *date = [self formatDate];
NSString *start = [NSString stringWithFormat:@"<?xml version=\"1.0\" encoding=\"utf-8\" ?>\r\n"
                   "<html xmlns=\"http://www.w3.org/1999/xhtml\" lang=\"en-us\">\r\n"
                   "<head>\r\n"
                   "<title>Created By</title>\r\n"
                   "<meta name=\"created\" content=\"%@\" />\r\n"
                   "</head>\r\n"
                   "<body>\r\n"
                   "<p>This is <b>Photo</b> <i>Created</i> note.</p>\r\n",date];

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

    self.imgObject = (ImageObjects *)[self.selectedImages objectAtIndex:i];

    FileModel *fileModel = [FileModel new];
    fileModel.fileData = self.imgObject.image_data;
    fileModel.fileName =  self.imgObject.imageName;
    fileModel.fileType = FileTypeImage;

    self.filePath = fileModel.getFileName;

    NSString *trimmedString = [self.filePath  stringByReplacingOccurrencesOfString:@" " withString:[NSString stringWithFormat:@"%d",i]];
    self.filePath = [trimmedString  stringByReplacingOccurrencesOfString:@":" withString:@""];

    NSString *middle = [NSString stringWithFormat:@"<img src=\"%@\" alt=\"image\" width=\"500\">\r\n",self.filePath];

    [selecedFileNames addObject:self.filePath];
    start = [start stringByAppendingString:middle];

}

start = [start stringByAppendingString:@"</body>\r\n"
         "</html>\r\n"];

NSString *boundary = [self generateBoundaryString];

NSString *pagesEndpoint = [NSString stringWithFormat:@"sections/%@/pages", selectedSectionId];
NSString *fullEndpoint = [serviceRootUrl stringByAppendingString:pagesEndpoint];

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

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

NSMutableData *body = [NSMutableData data];


[body appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"Presentation\"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[@"Content-Type:application/xhtml+xml\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"%@\r\n", start] dataUsingEncoding:NSUTF8StringEncoding]];

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

    self.imgObject = (ImageObjects *)[self.selectedImages objectAtIndex:i];

    FileModel *fileModel = [FileModel new];
    fileModel.fileData = self.imgObject.image_data;
    fileModel.fileName =  self.imgObject.imageName;
    fileModel.fileType = FileTypeImage;

    [body appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\" \r\n",[selecedFileNames objectAtIndex:i]] dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[@"Content-Type: image/jpeg\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[@"\r\n--" dataUsingEncoding:NSUTF8StringEncoding]];
    [body appendData:[NSData dataWithData:fileModel.fileData]];
    [body appendData:[@"--\r\n" dataUsingEncoding:NSUTF8StringEncoding]];

}

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


NSString *finalBody =[[NSString alloc] initWithData:body encoding:NSASCIIStringEncoding];

// set request body
[request setHTTPBody:body];

if (self.client)
{
    // Send the HTTP request.
    [self sendRequest:request];
}

I am successfully able to create page with images in OneNote but i am unable to see images on page. Please help me on this. Unable to find out what is the problem in request. Is there any problem is request i am creating ?


Solution

  • If you're getting a "413" response code, then that means you're exceeding the size of the request you're sending to the API. It depends on the total size of the images you are sending, not the number of images.

    Note that sending images via a Base64 string causes a 33% increase in its size (that is what the sample is doing). You can avoid this 33% hit by sending a multipart request. Additionally you can significantly reduce your image size by using a file format like JPEG (looks like you're using PNG, so you might have to still take extra steps to reduce the image size).

    Our iOS sample does exactly this in the function createPageWithImage

    NSString *attachmentPartName = @"pngattachment1";
    NSString *date = dateInISO8601Format();
    UIImage *logo = [UIImage imageNamed:@"Logo"];
    
    NSString *simpleHtml = [NSString stringWithFormat:
                            @"<html>"
                            "<head>"
                            "<title>A simple page with an image from iOS</title>"
                            "<meta name=\"created\" content=\"%@\" />"
                            "</head>"
                            "<body>"
                            "<h1>This is a page with an image on it</h1>"
                            "<img src=\"name:%@\" alt=\"A beautiful logo\" width=\"%.0f\" height=\"%.0f\" />"
                            "</body>"
                            "</html>", date, attachmentPartName, [logo size].width, [logo size].height];
    
    NSData *presentation = [simpleHtml dataUsingEncoding:NSUTF8StringEncoding];
    NSData *image1 = UIImageJPEGRepresentation(logo, 1.0);
    NSString *endpointToRequest = [ONSCPSCreateExamples getPagesEndpointUrlWithSectionName:sectionName];
    NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer] multipartFormRequestWithMethod:@"POST" URLString:endpointToRequest parameters:nil constructingBodyWithBlock: ^(id <AFMultipartFormData>formData) {
        [formData
         appendPartWithHeaders:@{
                                 @"Content-Disposition" : @"form-data; name=\"Presentation\"",
                                 @"Content-Type" : @"text/html"}
         body:presentation];
        [formData
         appendPartWithHeaders:@{
                                 @"Content-Disposition" : [NSString stringWithFormat:@"form-data; name=\"%@\"", attachmentPartName],
                                 @"Content-Type" : @"image/jpeg"}
         body:image1];
    }];
    

    If you have these headers:

    Content-Type: multipart/form-data; boundary=0FA204EB-20EA-4E56-99EC-5EF56D600E02
    

    And this body, it should work.

    --0FA204EB-20EA-4E56-99EC-5EF56D600E02
    Content-Disposition: form-data; name="Presentation"
    Content-Type: text/html
    <!DOCTYPE html>
    <html><head><title>Created By Photo</title>
    <meta name="created" content="2017-02-01T11:34:11+05:30" /></head><body><p>This is some <b>Photo</b> <i>Created</i> note.</p></body><h1>This is a note with image.</h1>
    <img src="name:2017-02-01060411+0000.JPG" alt="image" ></body></html>
    --0FA204EB-20EA-4E56-99EC-5EF56D600E02
    Content-Disposition: form-data; name="2017-02-01060411+0000.JPG"
    Content-Type: image/jpeg
    IMAGE
    --0FA204EB-20EA-4E56-99EC-5EF56D600E02--
    .