I have an app which is sending data collected via an email as an attachment. I use the following code to create and save the data to a file called 'leads.xml' in my docs folder.
NSArray *sysPath = NSSearchPathForDirectoriesInDomains( NSDocumentDirectory, NSUserDomainMask, YES );
NSString *sysFilePath = [sysPath objectAtIndex:0];
[picker addAttachmentData:sysFilePath mimeType:#"text/xml" fileName:#"leads.xml"];
.
.
.
[emailBody writeToFile:filePath atomically:YES];
I then try to send the saved file as an attachment using this code -
NSArray *sysPaths = NSSearchPathForDirectoriesInDomains( NSDocumentDirectory, NSUserDomainMask, YES );
NSString *docDirectory = [sysPaths objectAtIndex:0];
NSString *filePath = [NSString stringWithFormat:#"%#/leads.xml", docDirectory];
When it runs I get an error, what am I doing wrong?
The mail want a NSData object, contain the files content not a path.
You will need to load the file into a NSData object like:
NSArray *sysPaths = NSSearchPathForDirectoriesInDomains( NSDocumentDirectory, NSUserDomainMask, YES );
NSString *docDirectory = [sysPaths objectAtIndex:0];
NSString *filePath = [docDirectory stringByAppendingPathComponent:#"leads.xml"];
NSData *fileData = [NSData dataWithContentsOfFile:filePath];
[picker addAttachmentData:fileData mimeType:#"text/xml" fileName:#"leads.xml"];
You have to supply the data, not a file path:
NSData *data = [NSData dataWithContentsOfFile:sysFilePath];
[picker addAttachmentData:data mimeType:#"text/xml" fileName:fileName];
Docs:
- (void)addAttachmentData:(NSData*)attachment mimeType:(NSString*)mimeType fileName:(NSString*)filename
attachment:
The data to attach. Typically, this is the contents of a file that you want to include. This parameter must not be nil.
Try this code
if(mailController)
{
mailController.mailComposeDelegate = self;
// NSLog(#"current index:%d",currentIndex_);
NSString *string = [NSString stringWithFormat:#"00%d",currentIndex_+43];
// NSLog(#"string:%#",string);
NSString *imageIndex = [[NSBundle mainBundle] pathForResource:string ofType:#"jpg"];
NSData *myData = [[NSData alloc] initWithContentsOfFile:imageIndex];
[mailController addAttachmentData:myData mimeType:#"application/jpg" fileName:#"Report"];
[mailController setSubject:#"your subject"];
[mailController setMessageBody:#"" isHTML:NO];
[self presentModalViewController:mailController animated:YES];
[mailController release];
}
I am sending image here instead of it you can send your text file.
This may help you
Couple of things...
You can check the file system for the simulator at:
~/Library/Application Support/iPhone Simulator/5.0/Applications/...
and see if your file is actually being saved where you expect.
Second thing:
NSString actually has a load of convenience methods for working with file paths so you don't have to check for trailing slashes and other junk. You should always use them when working with file paths.
Working with Paths
+ pathWithComponents:
– pathComponents
– completePathIntoString:caseSensitive:matchesIntoArray:filterTypes:
– fileSystemRepresentation
– getFileSystemRepresentation:maxLength:
– isAbsolutePath
– lastPathComponent
– pathExtension
– stringByAbbreviatingWithTildeInPath
– stringByAppendingPathComponent:
– stringByAppendingPathExtension:
– stringByDeletingLastPathComponent
– stringByDeletingPathExtension
– stringByExpandingTildeInPath
– stringByResolvingSymlinksInPath
– stringByStandardizingPath
– stringsByAppendingPaths:
Related
I am currently creating a html file and storing it locally, i give the user the choice of sending the html by HTML or print.
For some reason it is failing to print. if i test -
if([UIPrintInteractionController canPrintData:myData]){
it doesn't get past this point.
Is it possible to print local HTML files if so how to go about it.
Dan
edit code to create html -
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *Daily = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:#"%#.html",self.title]];
[urlToLoad writeToFile:Daily atomically:YES encoding:NSUTF8StringEncoding error:NULL];
NSString *fileName = [NSString stringWithFormat:#"%#/%#.html", documentsDirectory,self.title];
NSData *myData = [NSData dataWithContentsOfFile:fileName];
[UIPrintInteractionController canPrintData:] is expecting the data to contain properly formatted PDF data, not HTML.
Try doing this instead:
UIPrintFormatter *formatter = [[UIMarkupTextPrintFormatter alloc] initWithMarkupText:html];
[[UIPrintInteractionController sharedPrintController] setPrintFormatter:formatter];
I', m using the Objective Zip library to compress several images i took. I came to the point (I guess) where I' zipping an image.
Now I'd like to send this zipped File with the mailcomposer. However I need to declare a "NSData object" within my mail function.
[picker addAttachmentData:"NSData object" mimeType:#"application/zip" fileName:#"test.zip"];
Here's a snippit of my code
-(IBAction)sendMail{
NSArray * paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"test.zip"];
NSArray *data = [[NSArray alloc] initWithObjects:#"first",#"second",#"third",nil];
NSString *docDir3 = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *pngFilePath4 = [NSString stringWithFormat:#"%#/foto2.jpg",paths];
[data writeToFile:pngFilePath4 atomically:YES];
NSData * fotoData = [[NSData alloc] initWithContentsOfFile:pngFilePath4];
NSFileManager *manager = [[NSFileManager alloc] init];
[manager removeItemAtPath:pngFilePath4 error:nil];
ZipFile *readFile = [[ZipFile alloc] initWithFileName:path mode:ZipFileModeCreate];
ZipWriteStream *stream = [readFile writeFileInZipWithName:#"foto2.jpg" compressionLevel:ZipCompressionLevelNone];
[stream writeData:fotoData];
[stream finishedWriting];
MFMailComposeViewController *picker = [[MFMailComposeViewController alloc] init];
picker.mailComposeDelegate=self;
[picker addAttachmentData:"NSData Object" mimeType:#"application/zip" fileName:#"test.zip"];
Class mailclass = (NSClassFromString(#"MFMailComposeViewController"));
if([mailclass canSendMail]){
[self presentModalViewController:picker animated:YES];
}
[readFile close];
[data2 release];
[fotoData release];
}
I think i need to make another NSData object from the readFile object and place this within the [picker attachmentData: method]. Hope someone can point me in the right direction.
EDIT
Still can't get this to work properly. It takes realy long to send the zip file (Even through wifi). When I open the zip image I get an error which says that the file cannot be opened. Here's my code:
NSArray * paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"test.zip"];
NSArray *data = [[NSArray alloc] initWithObjects:#"first",#"second", nil];
NSString *docDir3 = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *pngFilePath3 = [NSString stringWithFormat:#"%#/foto2.jpeg",docDir3];
NSData * imageData2 = [[[NSData alloc] initWithContentsOfFile:pngFilePath3] autorelease];
[data writeToFile:pngFilePath3 atomically:YES];
ZipFile *readFile = [[ZipFile alloc] initWithFileName:path mode:ZipFileModeCreate];
ZipWriteStream *stream = [readFile writeFileInZipWithName:#"foto2.jpeg" compressionLevel:ZipCompressionLevelNone];
[stream writeData:imageData2];
[stream finishedWriting];
MFMailComposeViewController *picker = [[MFMailComposeViewController alloc] init];
picker.mailComposeDelegate=self;
[picker addAttachmentData:[NSData dataWithContentsOfFile:path] mimeType:#"application/zip" fileName:#"test.zip"];
Class mailclass = (NSClassFromString(#"MFMailComposeViewController"));
if([mailclass canSendMail]){
[self presentModalViewController:picker animated:YES];
}
[data release];
[readFile close];
Thanks in advance for helping me out!
The ZipWriteStream is writing to path, and getting data from a file path is done using [NSData dataWithContentsOfFile:path].
[picker addAttachmentData:[NSData dataWithContentsOfFile:path]
mimeType:#"application/zip"
fileName:#"test.zip"];
Objective-Zip does throw exceptions when a write failure occurs so make sure you add a try/catch around the write operation and make sure your data is not nil.
How do I put my PDF into NSData? I have the location of the PDF as a string in my Documents Directory of the app. When I try to email it, I see the PDF in the body of the email (vs seeing an attachment icon. I don't know if that's normal or not). But when I receive the email on the other end, it does not have a PDF extension. What am I doing wrong? Thanks.
NSString *documentsDirectory = [self GetURLForPDF]; // I know this name is bad since it is really a NSString
NSLog(#"DocumentsDirectory: %#", documentsDirectory);
NSString *pdfName = [NSString stringWithFormat:#"%#/%#.pdf", documentsDirectory, title];
NSLog(#"pdfName: %#", pdfName);
NSData *pdfData = [NSData dataWithContentsOfFile:pdfName];
[mailComposer addAttachmentData:pdfData mimeType:#"application/pdf" fileName:title];
[self presentModalViewController:mailComposer animated:YES];
Based on how the pdfName variable is being set, it looks like your "title" value does not include the PDF suffix. Have you tried:
NSString *documentsDirectory = [self GetURLForPDF]; // I know this name is bad since it is really a NSString
NSLog(#"DocumentsDirectory: %#", documentsDirectory);
NSString *fullTitle = [NSString stringWithFormat:#"%#.pdf", title];
NSString *pdfName = [NSString stringWithFormat:#"%#/%#", documentsDirectory, fullTitle];
NSLog(#"pdfName: %#", pdfName);
NSData *pdfData = [NSData dataWithContentsOfFile:pdfName];
[mailComposer addAttachmentData:pdfData mimeType:#"application/pdf" fileName:fullTitle];
[self presentModalViewController:mailComposer animated:YES];
I am having trouble writing my file into the plist after going through many tutorials, other people's problems and attempting it for myself. I can read the plist with no problems but I cant update it. Below are my codes on how I am writing my data into the plist. Correct me if I made any mistake.
NSString *path = [[NSBundle mainBundle] pathForResource:#"EventAddress" ofType:#"plist"];
NSMutableDictionary *myDictionary = [[NSMutableDictionary alloc] initWithContentsOfFile:path];
NSArray* allmyData = [myDictionary allValues];
// creates and array to store only the event details
NSMutableArray *data = [[NSMutableArray alloc] initWithArray:allmyData];
[data addObject:[[NSMutableDictionary alloc] initWithObjectsAndKeys:tfAddress.text, #"Address", tvEvents.text, #"Events", nil]];
[myDictionary setValue:data forKey:#"Whampo"];
BOOL flag = [myDictionary writeToFile:path atomically:YES];
if (flag){
NSLog(#"write to plist success");
}
NSLog(#"%#", myDictionary);
[myDictionary release];
The path is correct, the file exists, my values in the textView and textField are in the array, but when it comes to the writeToFile, it does not reflect on the file located at the document directory.
EDIT 01:
I found this online, very similar to Nekto's suggestion. But I am thinking on how to implement my code with his. I think its pretty simple, but I cant seem to figure out how to.
NSArray *paths= NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentDirectory = [paths objectAtIndex:0];
NSString *plistDirectory = [NSString stringWithFormat:#"%#/Enterprise",documentDirectory];
NSString *mPath = [plistDirectory stringByAppendingPathComponent:#"Downloads.plist"];
[mDownloadsArray writeToFile:mPath atomically:YES];
iphonesdk.blogspot taken from that site.
EDIT 02:
I used Nekto's suggestion and it worked well. But I am curious why it is returning DocumentsEventAddress.plist rather than EventAddress.plist. My assumption is because of the
NSString *rootPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *plistPath = [rootPath stringByAppendingString:#"EventAddress.plist"];
Where rootPath is returning Document is that right?
I'm writing to file in such way:
NSString *errorDesc = nil;
NSString *rootPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *plistPath = [rootPath stringByAppendingString:TEMPLATES_PATH];
NSDictionary *dict = [NSDictionary dictionaryWithObject:templates forKey:#"templates"];
NSData *plistData = [NSPropertyListSerialization dataFromPropertyList:dict format:NSPropertyListXMLFormat_v1_0 errorDescription:&errorDesc];
if (plistData)
{
[plistData writeToFile:plistPath atomically:YES];
}else
{
NSLog(#"[Error] Application Did Enter Background {saving file error}: %#", errorDesc);
[errorDesc release];
}
Be sure to save file in app documents directory.
I don't believe you can write to a resource. Only files in the documents directory can be written to.
You can't write to files that are located in you Bundle.
The app bundle is read only.
I have used the MFMailComposeViewController to send the generated report(csv).
Now mail is sent to To:email id, & but when i checked the mails i did received the mail but attachment was not there.
Then I also tried MailComposer example :
https://developer.apple.com/iphone/library/samplecode/MailComposer/index.html
in which the png image is attached to mail demo. I also sent mail using that app, But same result image attachment is not delivered.
Help, to find what's the problem?
Thanks in advance.
Here is code in that app :
MFMailComposeViewController *picker = [[MFMailComposeViewController alloc] init];
picker.mailComposeDelegate = self;
[picker setSubject:#"Hello from California!"];
// Set up recipients
NSArray *toRecipients = [NSArray arrayWithObject:#"first#example.com"];
NSArray *ccRecipients = [NSArray arrayWithObjects:#"second#example.com", #"third#example.com", nil];
NSArray *bccRecipients = [NSArray arrayWithObject:#"fourth#example.com"];
[picker setToRecipients:toRecipients];
[picker setCcRecipients:ccRecipients];
[picker setBccRecipients:bccRecipients];
// Attach an image to the email
NSString *path = [[NSBundle mainBundle] pathForResource:#"rainy" ofType:#"png"];
NSData *myData = [NSData dataWithContentsOfFile:path];
[picker addAttachmentData:myData mimeType:#"image/png" fileName:#"rainy"];
// Fill out the email body text
NSString *emailBody = #"It is raining in sunny California!";
[picker setMessageBody:emailBody isHTML:NO];
[self presentModalViewController:picker animated:YES];
[picker release];
In my situation the email was sent fine from my iPhone, but there was no attachment when sending from my wife's iPhone. Turns out that her default account was set to her Yahoo account and that was not allowing attachments. I simply switched it to her mobile Me account and the attachment was made. I use gmail so I never had a problem.
in addition, I had tried switching the MIME type from text/csv to text/plain and that did not help. It worked either way on my iPhone and not at all on my wife's.
Hope this helps!
I have tried to attach .csv file with "text/plain" & I got success. I think you should try the same. best of luck.
I ran into the same problems and I fixed the problem by
doing a really hard look at two functions that I wrote:
One defines the filename from a .plist file, the other one actually sets the
location of the file (including it's path AND filename).
Using the right function to retrieve the filename in the MFMailViewController
fixed the issue:
-(NSString *)dataFilePath { //this gets the ,plist file
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
return [documentsDirectory stringByAppendingPathComponent:kFilename];
//----------------------------
-(NSString *)fileName { // this defines the fileName from the values in the .plist
NSString *patientDetails = [self dataFilePath];
NSArray *dataArray = [[NSArray alloc] initWithContentsOfFile:patientDetails];
NSString *firstName = [dataArray objectAtIndex:0];
NSString *lastName = [dataArray objectAtIndex:1];
NSString *fileName = [firstName stringByAppendingString:lastName];
return [fileName stringByAppendingString:#".csv"];
//-------------------------
-(NSString *)setFileLocation { //this puts name and folder together.
NSArray *sysPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docDirectory = [sysPaths objectAtIndex:0];
NSString *fileName = [self fileName];
NSString *fullFilePath = [NSString stringWithFormat:#"%#/%#", docDirectory,fileName];
// NSLog(#"Filepath is : %#",fullFilePath);
return fullFilePath;
}
//-------------------------
The last one is the function you want to call in your MFMailComposeViewController:
...
NSData *csvData = [NSData dataWithContentsOfFile:[self setFileLocation]];
[picker addAttachmentData:csvData mimeType:#"text/csv" fileName:fileName];
...
fileName, of course, is an NSString, retrieved by calling the fileName function:
NSString *fileName = [self fileName];
Hope this helps!
If your code looks okay I'll suspect that that myData didn't get loaded with data is nil. Put in an NSLog([myData description]) or use the debugger to check that myData is not nil.
I'm out of ideas. If I was stuck in this situation I would create a stand alone project with the example code you provided and see if I could get it working. Usually in these situations the code you are focusing on is probably correct and error is coming from somewhere else.
Also:
Check to see if the path variable is nil because that will cause the attachment to not appear.
Make sure there is a icon in message body the mail compose view. When you successfully add an attachment you should see the icon representation in the view.
And you probably want set your fileName to rainy.png, i.e. [picker addAttachmentData:myData mimeType:#"image/png" fileName:#"rainy.png"].
Good luck.