I'm following some examples of how to compress a video to reduce file size prior to uploading it to a server. Specifically, I've looked at this question here: How can I reduce the file size of a video created with UIImagePickerController?
However, I'm wondering where the best place to save the output is.
Even the AV foundation programming guide only provides this as an example:
NSError *outError;
NSURL *outputURL = <#NSURL object representing the URL where you want to save the video#>;
AVAssetWriter *assetWriter = [AVAssetWriter assetWriterWithURL:outputURL
fileType:AVFileTypeQuickTimeMovie
error:&outError];
BOOL success = (assetWriter != nil);
Again, looking for some guidance on exactly where it is I want to save the video!
Cheers,
Brendan
This is documents directory URL, just append your filename:
[[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
Almost the same for all others: library (NSLibraryDirectory)
You can write file in document directory using below code
defile document directory path
NSString *DocumentsDirectoryPath() {NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);NSString *documentsDirectoryPath = [paths objectAtIndex:0];return documentsDirectoryPath;}
and then
NSURL * outputURL = [NSURL fileURLWithPath:[DocumentsDirectoryPath() stringByAppendingPathComponent:#"yourfilename.mp4"]];
here mp4 is your file extention.
Related
I am saving video/image in document directory.Now once the image is saved in document directory I want to save its reference in my local database.So I am thinking I can save URL of the image in the local database.
So is it constant throughout my app?
It's not constant, i have observed every time you launch the app it'll be different, but your data is moved to this new path. You can save your file name in your database, and dynamically append this file name to NSDocument directory.
- (NSString *)documentsFilePath:(NSString *)fileName {
NSArray *dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docsDir = [dirPaths firstObject];
NSString *filePath = [docsDir stringByAppendingPathComponent:fileName];
return filePath;
}
- (void)storeFile:(NSString *)fileName {
NSString *filePath = [self documentsFilePath:fileName];
// create if needed
if (![[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
// Write your data to file system here...
}
}
- (void)deleteFile:(NSString *)fileName {
NSString *filePath = [self documentsFilePath:fileName];
if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
NSError *deleteErr = nil;
[[NSFileManager defaultManager] removeItemAtPath:filePath error:&deleteErr];
if (deleteErr) {
NSLog(#"Can't delete %#: %#", filePath, deleteErr);
}
}
}
Please handle nil checks and store only filename in DB
No, it's not constant. Whenever your app reinstall or updated on device the document directory will change, because when app installed on device os made an directory for app with some random id and each install this random it get changed by OS.
So, you need to make it dynamic own your own, like store the file name only and append the document directory path while using it.
I would suggest only saving the filename or subdirectory/filename (if you have a subdirectory) in the database and then only attaching that to the NSDocumentDirectory.
This will ensure that you always know where the file is...
NSDocumentDirectory is however consistent accross updates, so the files should remain in the document directory even if you update...
I want to save a mp4 video in my folder but when I open again the app, this file is nil. But when I save the file, I can open it, so it seems that it disappears from the folder.
Save:
NSData *videoData = [NSData dataWithContentsOfURL:exportUrl];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *tempPath = [documentsDirectory stringByAppendingFormat:#"/%#",videoName];
self.path_video_to_save = tempPath;
BOOL success = [videoData writeToFile:tempPath atomically:YES];
if (success)
NSLog(#"saved");
else
NSLog(#"not saved!!!!!!!!!!!!!!");
I get the success in true so it's ok and I can play my video well.
NSString *path_video = [dict objectForKey:#"path"]; //dictionary where I save the path, the same before and after closing app
NSData *videoData = [NSData dataWithContentsOfURL:[NSURL fileURLWithPath:path_video]];
if (videoData == nil){
NSLog(#"DATA NULL");
}
else
NSLog(#"DATA OK");
NSLog(#"PATH:%#", path_video);
self.player = [[MPMoviePlayerController alloc] initWithContentURL:[NSURL fileURLWithPath:path_video]];
and at this point it work fine.
But when I close and open again the app and I get the path, my app crash and I have the log "DATA NULL" I don't understand why when I close my app the file disappear... what's up?
thanks
This is because in iOS 8 + the name of the Application folder is renamed each time you launch it.
Check it in /Users/"your username"/Library/Developer/CoreSimulator/Devices/"device name"/data/Containers/Data/Application/"application name" (Test in simulator).
So, you have to save the path without the document directory. And when you are trying to retrieve the path you have to add the document directory before the path you saved previously.
Like let your custom folder name is "Save_Video" and file name is "video_01.mp4".
Your file saving path will be "Application document directory"/Save_Video/video_01.mp4
Then you have to store only "Save_Video/video_01.mp4"(in Database/ NSUserDefaults) and when you are retrieving the file the path should be
"Application document directory"/Save_Video/video_01.mp4
I just make a file browser for iOS, I just need to know how to open any kind of file in a UIWebview. I think the webview can open any kind of file, that's because I chose to use a UIWebView to view the files directly in the app. Now my question.
How to programmatically switch to a UIViewController in the same UIStoryBoard and display the file? The file URL is stored in a string called path.
This is how fare I am, I just need to add the file viewer.
Can someone help me?
-(void) displayFile:(NSString*)fileName
{
NSError *error = nil;
NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
TO get the filename
NSString *folderPath = [documentsDirectory stringByAppendingPathComponent:fileName];
if (![[NSFileManager defaultManager] fileExistsAtPath:folderPath]) //Optionally check if folder already hasn't existed.
{
// do something
}
}
Hope this helps you...
I'm trying to copy a downloaded file to a specific folder in the app's documents directory but can't seem to get it working. The code I'm using is:
NSString *itemPathString = #"http://pathToFolder/folder/myFile.doc";
NSURL *myUrl = [NSURL URLWithString:itemPathString];
NSArray *paths = [fm URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask];
NSURL *folderPath = [[paths objectAtIndex:0] URLByAppendingPathComponent:#"folder"];
NSURL *itemURL = [documentsPath URLByAppendingPathComponent:#"myFile.doc"];
// copy to documents directory asynchronously
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSFileManager *theFM = [[NSFileManager alloc] init];
NSError *error;
[theFM copyItemAtURL:myUrl toURL:itemURL error:&error];
}
});
I can retrieve the file OK but can't copy it. Can anyone tell me if there's anything wrong with the above code?
If downloading a file from a server, if it's a reasonably small file (e.g. measured in kb, not mb), you can use dataWithContentsOfURL. You can use that method to load the file into memory, and then use the NSData instance method writeToFile to save the file.
But, if it's a larger file, you will want to use NSURLConnection, which doesn't try to hold the whole file in memory, but rather writes it to the file system when appropriate. The trick here, though, is if you want to download multiple files, you either have to download them sequentially, or encapsulate the NSURLConnection and the NSOutputStream such that you can have separate copies of those for each simultaneous download.
I have uploaded a project, Download Manager that demonstrates what a NSURLConnection implementation might look like, but it's non-trivial. You might rather want to contemplate using an established, third-party library, such as ASIHTTPRequest or RestKit.
If you want to access a folder with a given name you should check if it exists and if not create it. That could quite easy be done like this:
NSString *folder = [documentsPath stringByAppendingPathComponent:folderName];
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error = nil;
if (![fileManager fileExistsAtPath:folder]) {
[fileManager createDirectoryAtPath:folder withIntermediateDirectories:YES attributes:nil error:&error];
}
if (error != nil) {
NSLog(#"Some error: %#", error);
return;
}
EDIT
If you want to check if the folder was created properly on your device got to Organizer -> Devices -> [YourDevelopingDeviceWhereTheAppWasInstalled] -> Applications -> [YourApplication]
In the lower section you should at least see some folders like Documents. And if successful your created folders as well.
You need to create any intermediate directories prior to copying files. Check in the Simulator folder to see wether the "folder" directory is created in the applications Documents-folder.
Path to simulator is /Users/$username/Library/Application Support/iPhone Simulator/
I am making a small app where the user can create a game profile, input some data and a picture that can be taken with the camera.
I save most of that profile data with the help of NSUserDefaults, but a friend discouraged me from saving the profile image in NSUserDefault.
What's the proper way to save and retrieve images locally in my app?
You should save it in Documents or Cache folder. Here is how to do it.
Saving into Documents folder:
NSString* path = [NSHomeDirectory() stringByAppendingString:#"/Documents/myImage.png"];
BOOL ok = [[NSFileManager defaultManager] createFileAtPath:path
contents:nil attributes:nil];
if (!ok)
{
NSLog(#"Error creating file %#", path);
}
else
{
NSFileHandle* myFileHandle = [NSFileHandle fileHandleForWritingAtPath:path];
[myFileHandle writeData:UIImagePNGRepresentation(yourImage)];
[myFileHandle closeFile];
}
Loading from Documents folder:
NSFileHandle* myFileHandle = [NSFileHandle fileHandleForReadingAtPath:path];
UIImage* loadedImage = [UIImage imageWithData:[myFileHandle readDataToEndOfFile]];
You can also use UIImageJPEGRepresentation to save your UIImage as a JPEG file. What's more if you want to save it in Cache directory, use:
[NSHomeDirectory() stringByAppendingString:#"/Library/Caches/"]
One way to do this is use the application's document directory. This is specific to a application and will not be visible to other applications.
How to create this:
Just add a static function to App Delegate and use the function where ever the path is required.
- (NSString )applicationDocumentDirectory {
/
Returns the path to the application's documents directory.
*/
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
return basePath;
}
Hope it Helped..
I think this("iphone-user-defaults-and-uiimages") post addresses your issue. Don't save blobs to a property list such as NSUserDefaults. In your case I would write to disk directly instead.