I have a video I'm fetching from my server and receiving as data. I'm trying to cover the raw data into a URL so that I can use it to instantiate an AVPlayerItem and play the video on the phone. However, this code returns nil when I print "videoDataString". If I print "videoData" there is a result though. Here is my code where I try to convert, is my mistake the encoding part?
let videoDataString = NSString(data: videoData, encoding: NSUTF8StringEncoding)
let videoURL = NSURL(string: String(videoDataString))
First Save your Video data to a file then try to access that as a file URL.
Here is an example.
NSString *filePath = [self documentsPathForFileName:#"video.mp4"];
NSData *videoAsData; // your data here
[videoAsData writeToFile:filePath atomically:YES];
// access video as URL
NSURL *videoFileURL = [NSURL fileURLWithPath:filePath];
- (NSString *)documentsPathForFileName:(NSString *)name
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);
NSString *documentsPath = [paths objectAtIndex:0];
return [documentsPath stringByAppendingPathComponent:name];
}
For Swift 3.0:
let filePath = self.documentsPathForFileName("video.mp4")
let videoAsData = NSData()
videoAsData.write(toFile: filePath, atomically: true)
let videoFileURL = NSURL(fileURLWithPath: filePath)
func documentsPathForFileName(name: String) -> String {
let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
return documentsPath.appending(name)
}
You cannot convert all strings to URL. URL is Uniform Resource Locator. That means it is a string containing the path to the file or resource in remote or local destination. If you want to keep your video data and instantiate video player with that video, first save the video data to a file, then instantiate video player with path to that file.
Use following code for this
let documentsURL = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask).first!
let videoURL = documentsURL.URLByAppendingPathComponent("video.mp4")//what ever your filename and extention
videoData.writeToURL(videoURL, atomically: true)
//uese videoURL to instantiate video player
Related
I want to convert local resource folder video file(12345.mp4) to base64 encoding string and then send into the server side from API but web team telling invalid base64 encoded string. Is this correct?
This is my code :
NSString *base64String = #"";
NSError *error;
NSData *videoData;
NSString *strVideoPath = [[NSBundle mainBundle] pathForResource:#"12345" ofType:#"mp4"];
videoData = [[NSData alloc]initWithContentsOfFile:strVideoPath options:NSDataReadingMappedIfSafe error:&error];
base64String = [videoData base64EncodedStringWithOptions:0];
In swift version you can convert video like this
*let tempURL = info[UIImagePickerController.InfoKey.mediaURL]
let data = NSData(contentsOf: tempURL as! URL)
print("\(String(describing: data?.length))")
if data?.length ?? 0 > 0{
guard data != nil else {
return
}
let base64String = data!.base64EncodedString(options: .lineLength64Characters)
self.video = base64String
}*
I'm looking for the Swift equivalent of the following Objective C common code.
In Objective C we had the following to redirect logging to the document folder instead of to the console:
- (void) redirectConsoleLogToDocumentFolder
{
NSArray *paths =
NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,
YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *logPath = [documentsDirectory
stringByAppendingPathComponent:#"console.log"];
freopen([logPath
cStringUsingEncoding:NSASCIIStringEncoding],"a+",stderr);
}
How is that done in Swift 2 ?
I suggest to read about logging in swift
func redirectConsoleLogToDocumentFolder() {
var paths: NSArray = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
var documentsDirectory: NSString = paths[0]
var logPath: NSString = documentsDirectory.stringByAppendingPathComponent("console.log")
var cstr = (logPath as NSString).UTF8String
freopen(cstr, "a+", stderr)
}
An updated answer for Swift 3.0
if let path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first {
let documentsDirectory = NSURL(fileURLWithPath: path)
let logPath = documentsDirectory.appendingPathComponent("console.log")!
freopen(logPath.absoluteString, "a+", stderr)
}
I have a UIImageView that allows a user to place and hold an image until it can be saved. The problem is, I can't figure out how to actually save and retrieve the image I've placed in the view.
I have retrieved and placed the image in the UIImageView like this:
//Get Image
- (void) getPicture:(id)sender {
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.allowsEditing = YES;
picker.sourceType = (sender == myPic) ? UIImagePickerControllerSourceTypeCamera : UIImagePickerControllerSourceTypeSavedPhotosAlbum;
[self presentModalViewController:picker animated:YES];
[picker release];
}
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage (UIImage *)image editingInfo:(NSDictionary *)editingInfo {
myPic.image = image;
[picker dismissModalViewControllerAnimated:YES];
}
It displays the selected image in my UIImageView just fine, but I have no idea how to save it. I'm saving all the other pieces of the view (mostly UITextfield) in Core Data. I've searched and searched, and tried many bits of code that people have suggested, but either I'm not entering the code correctly, or those suggestions don't work with the way I have my code set up. It's likely the former. I'd like to save the image in the UIImageView using the same action (a save button) I'm using to save the text in the UITextFields. Here's how I'm saving my UITextField info:
// Handle Save Button
- (void)save {
// Get Info From UI
[self.referringObject setValue:self.myInfo.text forKey:#"myInfo"];
Like I said earlier, I have tried several methods to get this to work, but can't get a grasp on it. For the first time in my life I've wanted to cause physical harm to an inanimate object, but I've managed to restrain myself.
I'd like to be able to save the image the user places into the UIImageView in the application's documents folder, and then be able to retrieve it and place it in another UIImageView for display when the user pushes that view onto the stack. Any help is greatly appreciated!
It's all good, man. Don't harm yourself or others.
You probably don't want to store these images in Core Data, since that can impact performance if the data set grows too large. Better to write the images to files.
NSData *pngData = UIImagePNGRepresentation(image);
This pulls out PNG data of the image you've captured. From here, you can write it to a file:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsPath = [paths objectAtIndex:0]; //Get the docs directory
NSString *filePath = [documentsPath stringByAppendingPathComponent:#"image.png"]; //Add the file name
[pngData writeToFile:filePath atomically:YES]; //Write the file
Reading it later works the same way. Build the path like we just did above, then:
NSData *pngData = [NSData dataWithContentsOfFile:filePath];
UIImage *image = [UIImage imageWithData:pngData];
What you'll probably want to do is make a method that creates path strings for you, since you don't want that code littered everywhere. It might look like this:
- (NSString *)documentsPathForFileName:(NSString *)name
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);
NSString *documentsPath = [paths objectAtIndex:0];
return [documentsPath stringByAppendingPathComponent:name];
}
Hope that's helpful.
Swift 3.0 version
let documentDirectoryPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString
let img = UIImage(named: "1.jpg")!// Or use whatever way to get the UIImage object
let imgPath = URL(fileURLWithPath: documentDirectoryPath.appendingPathComponent("1.jpg"))// Change extension if you want to save as PNG
do{
try UIImageJPEGRepresentation(img, 1.0)?.write(to: imgPath, options: .atomic)//Use UIImagePNGRepresentation if you want to save as PNG
}catch let error{
print(error.localizedDescription)
}
Swift 4 with extension
extension UIImage{
func saveImage(inDir:FileManager.SearchPathDirectory,name:String){
guard let documentDirectoryPath = FileManager.default.urls(for: inDir, in: .userDomainMask).first else {
return
}
let img = UIImage(named: "\(name).jpg")!
// Change extension if you want to save as PNG.
let imgPath = URL(fileURLWithPath: documentDirectoryPath.appendingPathComponent("\(name).jpg").absoluteString)
do {
try UIImageJPEGRepresentation(img, 0.5)?.write(to: imgPath, options: .atomic)
} catch {
print(error.localizedDescription)
}
}
}
Usage example
image.saveImage(inDir: .documentDirectory, name: "pic")
This is Fangming Ning's answer for Swift 4.2, updated with a recommended and more Swifty method for retrieving the document directory path and with better documentation. Credits to Fangming Ning for the new method as well.
guard let documentDirectoryPath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else {
return
}
//Using force unwrapping here because we're sure "1.jpg" exists. Remember, this is just an example.
let img = UIImage(named: "1.jpg")!
// Change extension if you want to save as PNG.
let imgPath = documentDirectoryPath.appendingPathComponent("1.jpg")
do {
//Use .pngData() if you want to save as PNG.
//.atomic is just an example here, check out other writing options as well. (see the link under this example)
//(atomic writes data to a temporary file first and sending that file to its final destination)
try img.jpegData(compressionQuality: 1)?.write(to: imgPath, options: .atomic)
} catch {
print(error.localizedDescription)
}
Check out all the possible Data writing options here.
#pragma mark - Save Image To Local Directory
- (void)saveImageToDocumentDirectoryWithImage:(UIImage *)capturedImage {
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0]; // Get documents folder
NSString *dataPath = [documentsDirectory stringByAppendingPathComponent:#"/images"];
//Create a folder inside Document Directory
if (![[NSFileManager defaultManager] fileExistsAtPath:dataPath])
[[NSFileManager defaultManager] createDirectoryAtPath:dataPath withIntermediateDirectories:NO attributes:nil error:&error]; //Create folder
NSString *imageName = [NSString stringWithFormat:#"%#/img_%#.png", dataPath, [self getRandomNumber]] ;
// save the file
if ([[NSFileManager defaultManager] fileExistsAtPath:imageName]) {
// delete if exist
[[NSFileManager defaultManager] removeItemAtPath:imageName error:nil];
}
NSData *imageDate = [NSData dataWithData:UIImagePNGRepresentation(capturedImage)];
[imageDate writeToFile: imageName atomically: YES];
}
#pragma mark - Generate Random Number
- (NSString *)getRandomNumber {
NSTimeInterval time = ([[NSDate date] timeIntervalSince1970]); // returned as a double
long digits = (long)time; // this is the first 10 digits
int decimalDigits = (int)(fmod(time, 1) * 1000); // this will get the 3 missing digits
//long timestamp = (digits * 1000) + decimalDigits;
NSString *timestampString = [NSString stringWithFormat:#"%ld%d",digits ,decimalDigits];
return timestampString;
}
In Swift:
let paths: [NSString?] = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .LocalDomainMask, true)
if let path = paths[0]?.stringByAppendingPathComponent(imageName) {
do {
try UIImagePNGRepresentation(image)?.writeToFile(path, options: .DataWritingAtomic)
} catch {
return
}
}
My app using GCDWebServer I get a photo from my iPhone album by using AssetsLibrary and I store them in NSDocumentDirectory. I just want to get access Url to this photo to show them in a web page.
There is my code :
[_webServer addHandlerForMethod:#"POST"
path:#"/"
requestClass:[GCDWebServerURLEncodedFormRequest class]
processBlock:^GCDWebServerResponse *(GCDWebServerRequest* request) {
ALAsset *asset = [self.arrayPictures objectAtIndex:0];
ALAssetRepresentation *rep = [asset defaultRepresentation];
CGImageRef iref = [rep fullResolutionImage];
UIImage *thumbnail = [UIImage imageWithCGImage:iref];
NSString* path ;
if (thumbnail != nil)
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
path = [[NSString alloc] initWithString:[documentsDirectory stringByAppendingPathComponent:#"test.png"]];
NSData* data = UIImagePNGRepresentation(thumbnail);
[data writeToFile:path atomically:YES];
}
NSURL *url = [NSURL fileURLWithPath:path];
NSString* html = [NSString stringWithFormat:#"<html><body><img src=\"%#\" width=\"400\" height=\"500\"/></body></html>", url];
return [GCDWebServerDataResponse responseWithHTML:html];
}];
For DocumentDirectory path
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *imagePath = [[NSString alloc] initWithString:[documentsDirectory stringByAppendingPathComponent:#"test.jpg"]];
NSURL *baseURL2 = [NSURL fileURLWithPath:documentsDirectory];
NSString* html2 = [NSString stringWithFormat:#"<html><body><img src=\"%#\" width=\"400\" height=\"500\"/></body></html>", imagePath];
[_webView loadHTMLString:html2 baseURL:baseURL2];
For Bundled resource
NSString *path = [[NSBundle mainBundle] pathForResource:#"ahsan" ofType:#"jpg"]; // path to your image source.
NSURL *baseURL = [NSURL fileURLWithPath:path];
NSString* html = [NSString stringWithFormat:#"<html><body><img src=\"%#\" width=\"400\" height=\"500\"/></body></html>", path];
Try this code.
GCDWebServer* webServer = [[GCDWebServer alloc] init];
[webServer addGETHandlerForBasePath:#"/" directoryPath:[[NSBundle mainBundle] bundlePath] indexFilename:nil cacheAge:3600 allowRangeRequests:YES];
[webServer runWithPort:8080];
Looks like nobody is answering the actual question here: this is not about uploading a photo from iOS to a web server or viewing it in a local UIWebView, but about serving that photo using GCDWebServer so that users can view it by connecting to the device using a web browser e.g. by going to http://my-device.local/photo-1234.jpg.
The sample code you provided has 2 major issues:
You are creating a handler for POST requests while you need to handle GET requests (POST is when submitting forms from web browsers, while GET is for regular web browsing and getting web pages).
Instead of returning the image data, you are returning an HTML webpage, which contains a URL to the image file locally (e.g. file:///some/path/photo-1234.jpg) instead of HTTP URL handled by GCDWebServer (e.g. http://my-device.local/photo-1234.jpg). File URLs do not make sense outside of the device itself and will not work.
If you have all the photos as files in your documents folder, you can simply add a GET handler to GCDWebServer to serve the contents of the entire documents folder:
[webServer addGETHandlerForBasePath:#"/"
directoryPath:<PATH_TO_DOCUMENTS_DIRECTORY>
indexFilename:nil
cacheAge:3600
allowRangeRequests:YES];
This is not a very good solution though, as it requires copying photos from the assets library into the documents folder, which is wasteful. Instead, consider dynamically serving the photo assets as I explain in my answer to a related question here: https://stackoverflow.com/a/31778726/463432.
You can create one GET request which will return all custom URLs of the photo assets.
After that create one handler of that custom URLs which will return requested URL image Data.
In a custom URL handler use below code
//Get PHAsset image name with extionsion.
let filename = NSURL(string: (asset as! PHAsset).originalFilename!)
// Retrive image data from PHAsset object
PHImageManager.default().requestImageData(for: asset as! PHAsset, options: nil, resultHandler: { (imageData, str, nil, info) in
//Check imageData is nil or not.
if (imageData) {
//Return image Data with contentType
let imageDatas = UIImagePNGRepresentation(imageData)
completionBlock!(GCDWebServerDataResponse(data: imageDatas, contentType: "image/\((filename?.pathExtension)!)"))
} else {
// Image retrive error message return.
let jsonResponse = ["type":"failed","Message":"Image not avilable."] as [String : Any]
completionBlock!(GCDWebServerDataResponse(jsonObject: jsonResponse))
}
})
// MARK:- Get File name from PHAsset.
extension PHAsset {
var originalFilename: String? {
var fname:String?
if #available(iOS 9.0, *) {
let resources = PHAssetResource.assetResources(for: self)
if let resource = resources.first {
fname = resource.originalFilename
}
}
if fname == nil {
// this is an undocumented workaround that works as of iOS 9.1
fname = self.value(forKey: "filename") as? String
}
return fname
}
}
I'm trying to load a UIImage from the documents directory and set it to a UIImageView as per below:
NSString *pngfile = [[MyUtil getLocalDirectory] stringByAppendingPathComponent:#"school.png"];
NSLog(#"%#", pngfile);
if ([[NSFileManager defaultManager] fileExistsAtPath:pngfile]) {
NSData *imageData = [NSData dataWithContentsOfFile:pngfile];
UIImage *img = [UIImage imageWithData:imageData];
[schoolImage setImage:img];
}
However, whenever I try the above, the image never loads. The image is in Documents/MyAppCustomDirectory/school.png. Is the above correct to load from that directory?
I also tried a few others: UIImage imageWithContentsOfFile, among other ways based on SO responses.
To get the documents directory you should use:
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [documentPaths objectAtIndex:0];
NSString *pngfile = [documentsDir stringByAppendingPathComponent:#"school.png"];
I'm not quite sure if you also need to append the 'MyAppCustomDirectory', but I don't think so.
Swift 4 Solution:
guard let documentsDirectory = try? FileManager.default.url(for: .documentDirectory,
in: .userDomainMask,
appropriateFor:nil,
create:false)
else {
// May never happen
print ("No Document directory Error")
return nil
}
// Construct your Path from device Documents Directory
var imagesDirectory = documentsDirectory
// Only if your images are un a subdirectory named 'images'
imagesDirectory.appendPathComponent("images", isDirectory: true)
// Add your file name to path
imagesDirectory.appendPathComponent("school.png")
// Create your UIImage?
let result = UIImage(contentsOfFile: imagesDirectory.path)