0

I am trying to attach a docx file when sending email but I am having trouble. These 2 lines are always nil. The variables filename and extension are not nil but file comes up as nil. Not sure if this matters but the docx file is dynamically generated, what if I were to use the NSData from the generated file instead of creating a new NSData variable here?

    filepath = /Users/myself/components/file.docx

NSString *file = [[NSBundle mainBundle] pathForResource:filename ofType:extension];
    NSData *fileData

= [NSData dataWithContentsOfFile:file];

here is the code

    -(void)sendEmail:(NSString*)filePath{
  if ([MFMailComposeViewController canSendMail])
  {
  mailComposer = [[MFMailComposeViewController alloc]init];
  mailComposer.mailComposeDelegate = self;
  [mailComposer setToRecipients:@[@"name@gmail.com"]];
  [mailComposer setSubject:@"Mobile File Attachment"];
  [mailComposer setMessageBody:@"DocX file attached" isHTML:NO];

    // Determine the file name and extension
    if(![filePath isEqual:nil])
    {
    NSArray *filepart = [filePath componentsSeparatedByString:@"."];
    NSString *filename = [filepart objectAtIndex:0];
    NSString *extension = [filepart objectAtIndex:1];

    // Get the resource path and read the file using NSData
    NSString *file = [[NSBundle mainBundle] pathForResource:filename ofType:extension];
    NSData *fileData = [NSData dataWithContentsOfFile:file];

    // Determine the MIME type
    NSString *mimeType;
    if ([extension isEqualToString:@"jpg"]) {
      mimeType = @"image/jpeg";
    } else if ([extension isEqualToString:@"png"]) {
      mimeType = @"image/png";
    } else if ([extension isEqualToString:@"doc"]) {
      mimeType = @"application/msword";
    } else if ([extension isEqualToString:@"docx"]) {
      mimeType = @"application/msword";
    } else if ([extension isEqualToString:@"ppt"]) {
      mimeType = @"application/vnd.ms-powerpoint";
    } else if ([extension isEqualToString:@"html"]) {
      mimeType = @"text/html";
    } else if ([extension isEqualToString:@"pdf"]) {
      mimeType = @"application/pdf";
    }

    // Add attachment
    [mailComposer addAttachmentData:fileData mimeType:mimeType fileName:filename];
    }

  [[UIApplication sharedApplication].keyWindow.rootViewController presentViewController:mailComposer animated:YES completion:nil];
    }

EDIT: add value of filePath and this is how I generate the file

  NSAttributedString *str = [[NSAttributedString alloc] initWithAttributedString:_textV.attributedText];



  //convert to html then write to a .docx file to export to docx
  NSData *data = [str dataFromRange:(NSRange){0, [str length]} documentAttributes:@{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType} error:NULL];

  [data writeToFile:@"/Users/myself/components/file.docx" atomically:YES];
Train
  • 3,420
  • 2
  • 29
  • 59

1 Answers1

1

The issue here as you've mentioned is those two lines - if the file is dynamically generated, it won't be in the main bundle - that's the bundle of an application (each app on OS X and iOS is a folder /"bundle" or "package"/, which contains other files. Using this method, you are retrieving files that are packaged with the app.

If you are generating the content, you are likely writing it to a different path (temp directory?) - hence the pathForResource: method returns nil (the resource is not found within the app bundle), and NSData initializer fails when the path is nil -> returns nil as well.

You most likely want this: NSData *fileData = [NSData dataWithContentsOfFile:filePath];.

Few notes:

  • do not use isEqual:nil. Simply use filePath != nil (it's easier to read and it's faster on execution).

  • NSString has a pathExtension property, which will retrieve the property for you.

  • using file paths is unofficially deprecated in favor of using URLs: NSURL *fileURL = [NSURL fileURLWithPath:filePath]; You should use URLs in new code.

Please, post a sample value of filePath if this doesn't help.

Charlie Monroe
  • 1,210
  • 9
  • 24
  • Thank you that makes much more sense. I was not taking into account the bundle file, Also thanks for the tips.But, I don't understand how to do this with a dynamically generated file. – Train Dec 30 '15 at 13:14
  • You already get some file path as the `filePath` parameter - you should use that as path instead of re-retrieving it from the `NSBundle`. I can't help further without additional information about how you generate/save the file. – Charlie Monroe Dec 30 '15 at 13:27