I'm trying to share a post from Instagram with swiftui, but it didn't work, I didn't have any problems while sharing a story, but the post screen doesn't open when sharing a post.
// plist
<key>LSApplicationQueriesSchemes</key>
<array>
<string>instagram</string>
<string>instagram-stories</string>
</array>
The below code worked for me.
Button {
if post.post_type != PostType.mp4.rawValue {
let imagedData = NSData(contentsOf: imageURL)!
InstagramManager.instance.postImage(image: UIImage(data: imagedData as Data)!) { success in
print("insgram shared success = \(success)")
}
} else {
let videoData = NSData(contentsOf: videoUrl!)
InstagramManager.instance.postVideoToInstagramFeed(videoData: videoData!)
}
import SwiftUI
import Photos
final class InstagramManager : NSObject {
public static let instance = InstagramManager()
func postImage(image: UIImage, result:((Bool)->Void)? = nil) {
guard let instagramURL = NSURL(string: "instagram://app") else {
if let result = result {
result(false)
}
return
}
// let image = image.scaleImageWithAspectToWidth(640)
do {
try PHPhotoLibrary.shared().performChangesAndWait {
let request = PHAssetChangeRequest.creationRequestForAsset(from: image)
let assetID = request.placeholderForCreatedAsset?.localIdentifier ?? ""
let shareURL = "instagram://library?LocalIdentifier=" + assetID
if UIApplication.shared.canOpenURL(instagramURL as URL) {
if let urlForRedirect = NSURL(string: shareURL) {
UIApplication.shared.open(URL(string: "\(urlForRedirect)")!)
}
}
}
} catch {
if let result = result {
result(false)
}
}
}
func postVideoToInstagramFeed(videoData: NSData) {
getLibraryPermissionIfNecessary { granted in
guard granted else { return }
}
PHPhotoLibrary.shared().performChanges({
let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0];
let filePath = "\(documentsPath)/\(Date().description).mp4"
videoData.write(toFile: filePath, atomically: true)
PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: URL(fileURLWithPath: filePath))
},
completionHandler: { success, error in
if success {
let fetchOptions = PHFetchOptions()
fetchOptions.sortDescriptors = [NSSortDescriptor(key: "modificationDate", ascending: false)]
let fetchResult = PHAsset.fetchAssets(with: .video, options: fetchOptions)
if let lastAsset = fetchResult.firstObject {
let localIdentifier = lastAsset.localIdentifier
let urlFeed = "instagram://library?LocalIdentifier=" + localIdentifier
guard
let url = URL(string: urlFeed)
else {
print("Could not open url")
return
}
DispatchQueue.main.async {
if UIApplication.shared.canOpenURL(url) {
if #available(iOS 10.0, *) {
UIApplication.shared.open(url, options: [:], completionHandler: { (success) in
print("Sucess")
})
}
else {
UIApplication.shared.openURL(url)
print("Sucess")
}
}
else {
print("Instagram not found")
}
}
}
}
else if let error = error {
print(error.localizedDescription)
}
else {
print("Could not save the video")
}
})
}
func getLibraryPermissionIfNecessary(completionHandler: #escaping (Bool) -> Void) {
guard PHPhotoLibrary.authorizationStatus() != .authorized else {
completionHandler(true)
return
}
PHPhotoLibrary.requestAuthorization { status in
completionHandler(status == .authorized)
}
}
}
import UIKit
extension UIImage {
// MARK: - UIImage+Resize
func scaleImageWithAspectToWidth(_ toWidth:CGFloat) -> UIImage {
let oldWidth:CGFloat = size.width
let scaleFactor:CGFloat = toWidth / oldWidth
let newHeight = self.size.height * scaleFactor
let newWidth = oldWidth * scaleFactor;
UIGraphicsBeginImageContext(CGSize(width: newWidth, height: newHeight))
draw(in: CGRect(x: 0, y: 0, width: newWidth, height: newHeight))
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage!
}
}
Related
I'm using rich notifications to display a https url image in a push notification. The image is full screen. The problem is the rich notification displays the center of the image which cuts off the top and bottom of the image.
I tried to shrink the image before sending it, but it still gets cut off.
I tried to shrink the image when retrieving it and displaying it but it still gets cut off.
How can I get the entire image to fit inside the rich notification attachment?
override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: #escaping (UNNotificationContent) -> Void) {
self.contentHandler = contentHandler
bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
func failEarly() {
contentHandler(request.content)
}
guard let bestAttemptContent = bestAttemptContent else { failEarly(); return }
guard let attachmentUrlString = request.content.userInfo["media-url"] as? String else { failEarly(): return }
guard let url = URL(string: attachmentUrlString) else { failEarly(); return }
URLSession.shared.downloadTask(with: url, completionHandler: { [weak self](tempLocation, response, error) -> Void in
if let error = error { return }
guard let location = tempLocation else { return }
guard let response = response else { return }
do {
let lastPathComponent = response.url?.lastPathComponent ?? ""
var attachmentID = UUID.init().uuidString + lastPathComponent
if response.suggestedFilename != nil {
attachmentID = UUID.init().uuidString + response.suggestedFilename!
}
let tempDict = NSTemporaryDirectory()
let tempFilePath = tempDict + attachmentID
try FileManager.default.moveItem(atPath: location.path, toPath: tempFilePath)
guard let image = UIImage(contentsOfFile: tempFilePath) else { return }
guard let resizedImage = NotificationService.resizeImage(image: image, newWidth: 200) else { return } // I went all the way down to 25 and it was just a blurry image
guard let imageData = resizedImage.jpegData(compressionQuality: 1.0) else { return }
let fileURL = URL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true)
.appendingPathComponent("pkm", isDirectory: false)
.appendingPathExtension("jpg")
try imageData.write(to: fileURL)
let attachment = try UNNotificationAttachment.init(identifier: "pkm.jpg", url: fileURL, options: nil)
bestAttemptContent.attachments.append(attachment)
}
catch { return }
OperationQueue.main.addOperation({[weak self]() -> Void in
self?.contentHandler?(bestAttemptContent);
})
}).resume()
}
extension NotificationService {
static func resizeImage(image: UIImage, newWidth: CGFloat) -> UIImage? {
let scale = newWidth / image.size.width
let newHeight = image.size.height * scale
UIGraphicsBeginImageContext(CGSize(width: newWidth, height: newHeight))
image.draw(in: CGRect(x: 0, y: 0, width: newWidth, height: newHeight))
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage
}
}
rich notification with the top and bottom cut off (no head, no bottom foot):
an example of the image before the top and bottom were cut off (has head and feet):
I couldn't get the full image but I could get the top half of it by cropping it using this answer
override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: #escaping (UNNotificationContent) -> Void) {
self.contentHandler = contentHandler
bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
func failEarly() {
contentHandler(request.content)
}
guard let bestAttemptContent = bestAttemptContent else { failEarly(); return }
guard let attachmentUrlString = request.content.userInfo["media-url"] as? String else { failEarly(): return }
guard let url = URL(string: attachmentUrlString) else { failEarly(); return }
URLSession.shared.downloadTask(with: url, completionHandler: { [weak self](tempLocation, response, error) -> Void in
if let error = error { return }
guard let location = tempLocation else { return }
guard let response = response else { return }
do {
let lastPathComponent = response.url?.lastPathComponent ?? ""
var attachmentID = UUID.init().uuidString + lastPathComponent
if response.suggestedFilename != nil {
attachmentID = UUID.init().uuidString + response.suggestedFilename!
}
let tempDict = NSTemporaryDirectory()
let tempFilePath = tempDict + attachmentID
try FileManager.default.moveItem(atPath: location.path, toPath: tempFilePath)
guard let image = UIImage(contentsOfFile: tempFilePath) else { return }
let croppedImage = NotificationService.cropImageInHalf(image: image) // cropping occurs here
guard let imageData = croppedImage.jpegData(compressionQuality: 1.0) else { return }
let fileURL = URL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true)
.appendingPathComponent("pkm", isDirectory: false)
.appendingPathExtension("jpg")
try imageData.write(to: fileURL)
let attachment = try UNNotificationAttachment.init(identifier: "pkm.jpg", url: fileURL, options: nil)
bestAttemptContent.attachments.append(attachment)
}
catch { return }
OperationQueue.main.addOperation({[weak self]() -> Void in
self?.contentHandler?(bestAttemptContent);
})
}).resume()
}
extension NotificationService {
static func cropImageInHalf(image: UIImage) -> UIImage {
let height = CGFloat(image.size.height * 0.5)
let rect = CGRect(x: 0, y: 0, width: image.size.width, height: height)
return cropImage(image: image, toRect: rect)
}
static func cropImage(image:UIImage, toRect rect:CGRect) -> UIImage {
let imageRef:CGImage = image.cgImage!.cropping(to: rect)!
let croppedImage:UIImage = UIImage(cgImage:imageRef)
return croppedImage
}
}
I am trying to save generated UIImage to Camera Roll.
I have necessary privacy string in Info.plist.
I tried couple of methods;
The error I am facing for PHPhotoLibrary is
Error Domain=com.apple.accounts Code=7 "(null)
The codes I have tried;
UIImageWriteToSavedPhotosAlbum(image!, nil, nil, nil);
The other one is;
PHPhotoLibrary.shared().savePhoto(image: image!, albumName: "AlbumName", completion: { (asset) in
if asset != nil
{
print("error")
}
})
func savePhoto(image:UIImage, albumName:String, completion:((PHAsset?)->())? = nil) {
func save() {
if let album = PHPhotoLibrary.shared().findAlbum(albumName: albumName) {
PHPhotoLibrary.shared().saveImage(image: image, album: album, completion: completion)
} else {
PHPhotoLibrary.shared().createAlbum(albumName: albumName, completion: { (collection) in
if let collection = collection {
PHPhotoLibrary.shared().saveImage(image: image, album: collection, completion: completion)
} else {
completion?(nil)
}
})
}
}
if PHPhotoLibrary.authorizationStatus() == .authorized {
save()
} else {
PHPhotoLibrary.requestAuthorization({ (status) in
if status == .authorized {
save()
}
})
}
}
// MARK: - Private
fileprivate func findAlbum(albumName: String) -> PHAssetCollection? {
let fetchOptions = PHFetchOptions()
fetchOptions.predicate = NSPredicate(format: "title = %#", albumName)
let fetchResult : PHFetchResult = PHAssetCollection.fetchAssetCollections(with: .album, subtype: .any, options: fetchOptions)
guard let photoAlbum = fetchResult.firstObject else {
return nil
}
return photoAlbum
}
fileprivate func createAlbum(albumName: String, completion: #escaping (PHAssetCollection?)->()) {
var albumPlaceholder: PHObjectPlaceholder?
PHPhotoLibrary.shared().performChanges({
let createAlbumRequest = PHAssetCollectionChangeRequest.creationRequestForAssetCollection(withTitle: albumName)
albumPlaceholder = createAlbumRequest.placeholderForCreatedAssetCollection
}, completionHandler: { success, error in
if success {
guard let placeholder = albumPlaceholder else {
completion(nil)
return
}
let fetchResult = PHAssetCollection.fetchAssetCollections(withLocalIdentifiers: [placeholder.localIdentifier], options: nil)
guard let album = fetchResult.firstObject else {
completion(nil)
return
}
completion(album)
} else {
completion(nil)
}
})
}
fileprivate func saveImage(image: UIImage, album: PHAssetCollection, completion:((PHAsset?)->())? = nil) {
var placeholder: PHObjectPlaceholder?
PHPhotoLibrary.shared().performChanges({
let createAssetRequest = PHAssetChangeRequest.creationRequestForAsset(from: image)
guard let albumChangeRequest = PHAssetCollectionChangeRequest(for: album),
let photoPlaceholder = createAssetRequest.placeholderForCreatedAsset else { return }
placeholder = photoPlaceholder
let fastEnumeration = NSArray(array: [photoPlaceholder] as [PHObjectPlaceholder])
albumChangeRequest.addAssets(fastEnumeration)
}, completionHandler: { success, error in
guard let placeholder = placeholder else {
completion?(nil)
return
}
if success {
let assets:PHFetchResult<PHAsset> = PHAsset.fetchAssets(withLocalIdentifiers: [placeholder.localIdentifier], options: nil)
let asset:PHAsset? = assets.firstObject
completion?(asset)
} else {
completion?(nil)
}
})
}
Could you please help me on figuring out this?
BR,
Erdem
I have figured it out.
The problem is I have been creating QR Image that is created with CIFilter is CIImage.
It returns error code = -1
You need to create UIImage from CGImage not CIImage
if let output = filter.outputImage?.transformed(by: transform) {
let context = CIContext()
guard let cgImage = context.createCGImage(output, from: output.extent) else { return nil }
return UIImage(cgImage: cgImage)
}
func shareVideoToInstagram() {
let strURL = "http://mobmp4.org/files/data/2480/Tutak%20Tutak%20Tutiya%20Title%20Song%20-%20Remix%20-%20Drunx%20-%20Mp4.mp4"
let caption = "Some Preloaded Caption"
let captionStr = caption.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)! as String
let videoURL = URL(fileURLWithPath: strURL, isDirectory: false)
let library = ALAssetsLibrary()
library.writeVideoAtPath(toSavedPhotosAlbum: videoURL) { (newURL, error) in
if let instagramURL = NSURL(string: "instagram://library?AssetPath=\(videoURL.absoluteString.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)!)&InstagramCaption=\(captionStr)") {
print(instagramURL)
if UIApplication.shared.canOpenURL(instagramURL as URL) {
UIApplication.shared.openURL(instagramURL as URL)
}
} else {
print("NO")
}
}
}
I got instagramURL like this:
instagram://library?AssetPath=file:%2F%2F%2Fhttp:%2Fmobmp4.org%2Ffiles%2Fdata%2F2480%2FTutak%252520Tutak%252520Tutiya%252520Title%252520Song%252520-%252520Remix%252520-%252520Drunx%252520-%252520Mp4.mp4&InstagramCaption=Some%20Preloaded%20Caption
And I successfully openURL but I can not found my video which I want to share on instagram.
func shareVideoToInstagram() {
let videoFilePath = "http://mobmp4.org/files/data/2480/Tutak%20Tutak%20Tutiya%20Title%20Song%20-%20Remix%20-%20Drunx%20-%20Mp4.mp4"
let instagramURL = NSURL(string: "instagram://app")
if (UIApplication.shared.canOpenURL(instagramURL! as URL)) {
let url = URL(string: ("instagram://library?AssetPath="+videoFilePath))
if UIApplication.shared.canOpenURL(url!) {
UIApplication.shared.open(url!, options: [:], completionHandler:nil)
}
} else {
print(" Instagram isn't installed ")
}
}
First, you need a NSData from video:
guard
let videoPath = "http://mobmp4.org/files/data/2480/Tutak%20Tutak%20Tutiya%20Title%20Song%20-%20Remix%20-%20Drunx%20-%20Mp4.mp4",
let videoUrl = URL(string: videoPath),
let videoData = NSData(contentsOf: videoUrl)
else {
return
}
postVideoToInstagramFeed(videoData: videoData)
and share with the function:
func postVideoToInstagramFeed(videoData: NSData) {
getLibraryPermissionIfNecessary { granted in
guard granted else { return }
}
PHPhotoLibrary.shared().performChanges({
let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0];
let filePath = "\(documentsPath)/\(Date().description).mp4"
videoData.write(toFile: filePath, atomically: true)
PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: URL(fileURLWithPath: filePath))
},
completionHandler: { success, error in
if success {
let fetchOptions = PHFetchOptions()
fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
let fetchResult = PHAsset.fetchAssets(with: .video, options: fetchOptions)
if let lastAsset = fetchResult.firstObject {
let localIdentifier = lastAsset.localIdentifier
let urlFeed = "instagram://library?LocalIdentifier=" + localIdentifier
guard
let url = URL(string: urlFeed)
else {
print("Could not open url")
return
}
DispatchQueue.main.async {
if UIApplication.shared.canOpenURL(url) {
if #available(iOS 10.0, *) {
UIApplication.shared.open(url, options: [:], completionHandler: { (success) in
print("Sucess")
})
}
else {
UIApplication.shared.openURL(url)
print("Sucess")
}
}
else {
print("Instagram not found")
}
}
}
}
else if let error = error {
print(error.localizedDescription)
}
else {
print("Could not save the video")
}
})
}
func getLibraryPermissionIfNecessary(completionHandler: #escaping (Bool) -> Void) {
guard PHPhotoLibrary.authorizationStatus() != .authorized else {
completionHandler(true)
return
}
PHPhotoLibrary.requestAuthorization { status in
completionHandler(status == .authorized)
}
}
How to record video automatically in iOS without user interaction on camera controls ?
the requirement is to record video from front camera on open a view but condition is camera controls are disable,
video record and save automatic on going and back from that view.
Swift 3.0
finally i solve the problem just copy and paste the whole code and
connect outlet and this working fine.
class TestViewController: UIViewController {
#IBOutlet weak var myView: UIView!
var session: AVCaptureSession?
var userreponsevideoData = NSData()
var userreponsethumbimageData = NSData()
override func viewDidLoad() {
super.viewDidLoad()
createSession()
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
}
func createSession() {
var input: AVCaptureDeviceInput?
let movieFileOutput = AVCaptureMovieFileOutput()
var prevLayer: AVCaptureVideoPreviewLayer?
prevLayer?.frame.size = myView.frame.size
session = AVCaptureSession()
let error: NSError? = nil
do { input = try AVCaptureDeviceInput(device: self.cameraWithPosition(.Front)!) } catch {return}
if error == nil {
session?.addInput(input)
} else {
print("camera input error: \(error)")
}
prevLayer = AVCaptureVideoPreviewLayer(session: session)
prevLayer?.frame.size = myView.frame.size
prevLayer?.videoGravity = AVLayerVideoGravityResizeAspectFill
prevLayer?.connection.videoOrientation = .Portrait
myView.layer.addSublayer(prevLayer!)
let documentsURL = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)[0]
let filemainurl = NSURL(string: ("\(documentsURL.URLByAppendingPathComponent("temp")!)" + ".mov"))
let maxDuration: CMTime = CMTimeMake(600, 10)
movieFileOutput.maxRecordedDuration = maxDuration
movieFileOutput.minFreeDiskSpaceLimit = 1024 * 1024
if self.session!.canAddOutput(movieFileOutput) {
self.session!.addOutput(movieFileOutput)
}
session?.startRunning()
movieFileOutput.startRecordingToOutputFileURL(filemainurl, recordingDelegate: self)
}
func cameraWithPosition(position: AVCaptureDevicePosition) -> AVCaptureDevice? {
let devices = AVCaptureDevice.devicesWithMediaType(AVMediaTypeVideo)
for device in devices {
if device.position == position {
return device as? AVCaptureDevice
}
}
return nil
}
#IBAction func pressbackbutton(sender: AnyObject) {
session?.stopRunning()
}
}
extension TestViewController: AVCaptureFileOutputRecordingDelegate
{
func captureOutput(captureOutput: AVCaptureFileOutput!, didStartRecordingToOutputFileAtURL fileURL: NSURL!, fromConnections connections: [AnyObject]!) {
print(fileURL)
}
func captureOutput(captureOutput: AVCaptureFileOutput!, didFinishRecordingToOutputFileAtURL outputFileURL: NSURL!, fromConnections connections: [AnyObject]!, error: NSError!) {
print(outputFileURL)
let filemainurl = outputFileURL
do
{
let asset = AVURLAsset(URL: filemainurl, options: nil)
print(asset)
let imgGenerator = AVAssetImageGenerator(asset: asset)
imgGenerator.appliesPreferredTrackTransform = true
let cgImage = try imgGenerator.copyCGImageAtTime(CMTimeMake(0, 1), actualTime: nil)
let uiImage = UIImage(CGImage: cgImage)
userreponsethumbimageData = NSData(contentsOfURL: filemainurl)!
print(userreponsethumbimageData.length)
print(uiImage)
// imageData = UIImageJPEGRepresentation(uiImage, 0.1)
}
catch let error as NSError
{
print(error)
return
}
SVProgressHUD.showWithMaskType(SVProgressHUDMaskType.Clear)
let VideoFilePath = NSURL(fileURLWithPath: NSTemporaryDirectory()).URLByAppendingPathComponent("mergeVideo\(arc4random()%1000)d")!.URLByAppendingPathExtension("mp4")!.absoluteString
if NSFileManager.defaultManager().fileExistsAtPath(VideoFilePath!)
{
do
{
try NSFileManager.defaultManager().removeItemAtPath(VideoFilePath!)
}
catch { }
}
let tempfilemainurl = NSURL(string: VideoFilePath!)!
let sourceAsset = AVURLAsset(URL: filemainurl!, options: nil)
let assetExport: AVAssetExportSession = AVAssetExportSession(asset: sourceAsset, presetName: AVAssetExportPresetMediumQuality)!
assetExport.outputFileType = AVFileTypeQuickTimeMovie
assetExport.outputURL = tempfilemainurl
assetExport.exportAsynchronouslyWithCompletionHandler { () -> Void in
switch assetExport.status
{
case AVAssetExportSessionStatus.Completed:
dispatch_async(dispatch_get_main_queue(),
{
do
{
SVProgressHUD .dismiss()
self.userreponsevideoData = try NSData(contentsOfURL: tempfilemainurl, options: NSDataReadingOptions())
print("MB - \(self.userreponsevideoData.length) byte")
}
catch
{
SVProgressHUD .dismiss()
print(error)
}
})
case AVAssetExportSessionStatus.Failed:
print("failed \(assetExport.error)")
case AVAssetExportSessionStatus.Cancelled:
print("cancelled \(assetExport.error)")
default:
print("complete")
SVProgressHUD .dismiss()
}
}
}
}
Here is the swift 4.1 version
#objc func longPress(gesture: UILongPressGestureRecognizer) {
if gesture.state == UIGestureRecognizerState.began {
print("Long Press")
captureButton.setImage(UIImage(named: "recording"), for:.normal)
createSession()
}else if gesture.state == UIGestureRecognizerState.changed {
}
else if gesture.state == UIGestureRecognizerState.ended {
captureButton.setImage(UIImage(named: "camaraTap"), for:.normal)
session?.stopRunning()
}
}
func createSession() {
var input: AVCaptureDeviceInput?
let movieFileOutput = AVCaptureMovieFileOutput()
videosPreviewLayer?.frame.size = photoPreviewImageView.frame.size
session = AVCaptureSession()
let error: NSError? = nil
do { input = try AVCaptureDeviceInput(device: self.cameraWithPosition(position: .back)!) } catch {return}
if error == nil {
session?.addInput(input!)
} else {
print("camera input error: \(String(describing: error))")
}
videosPreviewLayer = AVCaptureVideoPreviewLayer(session: session!)
videosPreviewLayer?.frame.size = self.photoPreviewImageView.frame.size
videosPreviewLayer?.videoGravity = AVLayerVideoGravity.resizeAspectFill
videosPreviewLayer?.connection?.videoOrientation = .portrait
photoPreviewImageView.layer.sublayers?.forEach { $0.removeFromSuperlayer() }
photoPreviewImageView.layer.addSublayer(videosPreviewLayer!)
switchCameraButton.isHidden=true
flashButton.isHidden=true
msgLabel.isHidden=true
galleryCollectionView.isHidden=true
timerLabel.isHidden=false
let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
fileURL = URL(string:"\(documentsURL.appendingPathComponent("temp"))" + ".mov")
print("*****fileurl%#",fileURL ?? "00000")
let maxDuration: CMTime = CMTimeMake(600, 10)
movieFileOutput.maxRecordedDuration = maxDuration
movieFileOutput.minFreeDiskSpaceLimit = 1024 * 1024
if self.session!.canAddOutput(movieFileOutput) {
self.session!.addOutput(movieFileOutput)
}
session?.startRunning()
movieFileOutput.startRecording(to: fileURL!, recordingDelegate: self)
}
func cameraWithPosition(position: AVCaptureDevice.Position) -> AVCaptureDevice? {
let devices = AVCaptureDevice.devices(for: AVMediaType.video)
for device in devices {
if device.position == position {
return device
}
}
return nil
}
}
extension SwipeGallerymainViewController: AVCaptureFileOutputRecordingDelegate
{
func fileOutput(_ output: AVCaptureFileOutput, didFinishRecordingTo outputFileURL: URL, from connections: [AVCaptureConnection], error: Error?) {
print(outputFileURL)
let filemainurl = outputFileURL
do
{
let asset = AVURLAsset(url:filemainurl as URL, options:nil)
print(asset)
let imgGenerator = AVAssetImageGenerator(asset: asset)
imgGenerator.appliesPreferredTrackTransform = true
let cgImage = try imgGenerator.copyCGImage(at: CMTimeMake(0, 1), actualTime: nil)
let uiImage = UIImage(cgImage: cgImage)
previewImage = uiImage
userreponsethumbimageData = NSData(contentsOf: filemainurl as URL)!
print(userreponsethumbimageData.length)
print(uiImage)
// imageData = UIImageJPEGRepresentation(uiImage, 0.1)
}
catch let error as NSError
{
print(error)
return
}
let VideoFilePath = URL(fileURLWithPath:NSTemporaryDirectory()).appendingPathComponent("mergeVideo\(arc4random()%1000)d").appendingPathExtension("mp4").absoluteString
if FileManager.default.fileExists(atPath: VideoFilePath)
{
print("exist")
do
{
try FileManager.default.removeItem(atPath: VideoFilePath)
}
catch { }
}
let tempfilemainurl = NSURL(string: VideoFilePath)!
let sourceAsset = AVURLAsset(url:filemainurl as URL, options:nil)
let assetExport: AVAssetExportSession = AVAssetExportSession(asset: sourceAsset, presetName: AVAssetExportPresetMediumQuality)!
assetExport.outputFileType = AVFileType.mov
assetExport.outputURL = tempfilemainurl as URL
assetExport.exportAsynchronously { () -> Void in
switch assetExport.status
{
case AVAssetExportSessionStatus.completed:
DispatchQueue.main.async {
do
{
// SVProgressHUD .dismiss()
self.userreponsevideoData = try NSData(contentsOf: tempfilemainurl as URL, options: NSData.ReadingOptions())
print("MB - \(self.userreponsevideoData.length) byte")
self.isVideoLoad=true
self.performSegue(withIdentifier:"previewSegue", sender:self)
}
catch
{
// SVProgressHUD .dismiss()
print(error)
}
}
case AVAssetExportSessionStatus.failed:
print("failed \(String(describing: assetExport.error))")
case AVAssetExportSessionStatus.cancelled:
print("cancelled \(String(describing: assetExport.error))")
default:
print("complete")
// SVProgressHUD .dismiss()
}
}
}
func captureOutput(captureOutput: AVCaptureFileOutput!, didStartRecordingToOutputFileAtURL fileURL: NSURL!, fromConnections connections: [AnyObject]!) {
print(fileURL)
}
}
I'm trying to upload an image to a bucket S3 AWS, I am using the following code. but do I use it to upload to an image stored in a variable or imageView.image?
let ext = "jpg"
let imageURL = NSBundle.mainBundle().URLForResource("imagename", withExtension: ext)
print("imageURL:\(imageURL)")
let uploadRequest = AWSS3TransferManagerUploadRequest()
uploadRequest.body = imageURL
uploadRequest.key = NSProcessInfo.processInfo().globallyUniqueString + "." + ext
uploadRequest.bucket = S3BucketName
uploadRequest.contentType = "image/" + ext
let transferManager = AWSS3TransferManager.defaultS3TransferManager()
transferManager.upload(uploadRequest).continueWithBlock { (task) -> AnyObject! in
if let error = task.error {
print("Upload failed ❌ (\(error))")
}
if let exception = task.exception {
print("Upload failed ❌ (\(exception))")
}
if task.result != nil {
let s3URL = NSURL(string: "http://s3.amazonaws.com/\(self.S3BucketName)/\(uploadRequest.key!)")!
print("Uploaded to:\n\(s3URL)")
}
else {
print("Unexpected empty result.")
}
return nil
}
AWSS3TransferManager is deprecated. Use AWSS3TransferUtility instead.
The transfer utility provides methods for both single-part and
multipart uploads. When a transfer uses multipart upload, the data is
chunked into a number of 5 MB parts which are transferred in parallel
for increased speed.
func uploadFile(withImage image: UIImage) {
let access = "YOUR ACCESS KEY"
let secret = "YOUR SECRET KEY"
let credentials = AWSStaticCredentialsProvider(accessKey: access, secretKey: secret)
let configuration = AWSServiceConfiguration(region: AWSRegionType.USEast1, credentialsProvider: credentials)
AWSServiceManager.default().defaultServiceConfiguration = configuration
let s3BucketName = "YOUR BUCKET NAME"
let compressedImage = image.resizedImage(newSize: CGSize(width: 80, height: 80))
let data: Data = compressedImage.pngData()!
let remoteName = generateRandomStringWithLength(length: 12)+"."+data.format
print("REMOTE NAME : ",remoteName)
let expression = AWSS3TransferUtilityUploadExpression()
expression.progressBlock = { (task, progress) in
DispatchQueue.main.async(execute: {
// Update a progress bar
})
}
var completionHandler: AWSS3TransferUtilityUploadCompletionHandlerBlock?
completionHandler = { (task, error) -> Void in
DispatchQueue.main.async(execute: {
// Do something e.g. Alert a user for transfer completion.
// On failed uploads, `error` contains the error object.
})
}
let transferUtility = AWSS3TransferUtility.default()
transferUtility.uploadData(data, bucket: s3BucketName, key: remoteName, contentType: "image/"+data.format, expression: expression, completionHandler: completionHandler).continueWith { (task) -> Any? in
if let error = task.error {
print("Error : \(error.localizedDescription)")
}
if task.result != nil {
let url = AWSS3.default().configuration.endpoint.url
let publicURL = url?.appendingPathComponent(S3BucketName).appendingPathComponent(remoteName)
if let absoluteString = publicURL?.absoluteString {
// Set image with URL
print("Image URL : ",absoluteString)
}
}
return nil
}
}
For generating random strings for remote name.
func generateRandomStringWithLength(length: Int) -> String {
let randomString: NSMutableString = NSMutableString(capacity: length)
let letters: NSMutableString = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
var i: Int = 0
while i < length {
let randomIndex: Int = Int(arc4random_uniform(UInt32(letters.length)))
randomString.append("\(Character( UnicodeScalar( letters.character(at: randomIndex))!))")
i += 1
}
return String(randomString)
}
For resizing the image and data formatting. Use below Image and Data extensions.
extension UIImage {
func resizedImage(newSize: CGSize) -> UIImage {
guard self.size != newSize else { return self }
UIGraphicsBeginImageContextWithOptions(newSize, false, 0.0);
self.draw(in: CGRect(x: 0, y: 0, width: newSize.width, height: newSize.height))
let newImage: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
return newImage
}
}
extension Data {
var format: String {
let array = [UInt8](self)
let ext: String
switch (array[0]) {
case 0xFF:
ext = "jpg"
case 0x89:
ext = "png"
case 0x47:
ext = "gif"
case 0x49, 0x4D :
ext = "tiff"
default:
ext = "unknown"
}
return ext
}
}
I Have modified your code, try this
let ext = "jpg"
let imageURL = NSBundle.mainBundle().URLForResource("imagename", withExtension: ext)
print("imageURL:\(imageURL)")
let uploadRequest = AWSS3TransferManagerUploadRequest()
uploadRequest.body = imageURL
uploadRequest.key = "\(NSProcessInfo.processInfo().globallyUniqueString).\(ext)"
uploadRequest.bucket = S3BucketName
uploadRequest.contentType = "image/\(ext)"
let transferManager = AWSS3TransferManager.defaultS3TransferManager()
transferManager.upload(uploadRequest).continueWithBlock { (task) -> AnyObject! in
if let error = task.error {
print("Upload failed ❌ (\(error))")
}
if let exception = task.exception {
print("Upload failed ❌ (\(exception))")
}
if task.result != nil {
let s3URL = NSURL(string: "http://s3.amazonaws.com/\(self.S3BucketName)/\(uploadRequest.key!)")!
print("Uploaded to:\n\(s3URL)")
}
else {
print("Unexpected empty result.")
}
return nil
}
or you can use my code below to upload to AWS s3, its worked fine for me. This code is written in swift 3.
func uploadButtonPressed(_ sender: AnyObject) {
if documentImageView.image == nil {
// Do something to wake up user :)
} else {
let image = documentImageView.image!
let fileManager = FileManager.default
let path = (NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString).appendingPathComponent("\(imageName!).jpeg")
let imageData = UIImageJPEGRepresentation(image, 0.99)
fileManager.createFile(atPath: path as String, contents: imageData, attributes: nil)
let fileUrl = NSURL(fileURLWithPath: path)
var uploadRequest = AWSS3TransferManagerUploadRequest()
uploadRequest?.bucket = "BucketName"
uploadRequest?.key = "key.jpeg"
uploadRequest?.contentType = "image/jpeg"
uploadRequest?.body = fileUrl as URL!
uploadRequest?.serverSideEncryption = AWSS3ServerSideEncryption.awsKms
uploadRequest?.uploadProgress = { (bytesSent, totalBytesSent, totalBytesExpectedToSend) -> Void in
DispatchQueue.main.async(execute: {
self.amountUploaded = totalBytesSent // To show the updating data status in label.
self.fileSize = totalBytesExpectedToSend
})
}
let transferManager = AWSS3TransferManager.default()
transferManager?.upload(uploadRequest).continue(with: AWSExecutor.mainThread(), withSuccessBlock: { (taskk: AWSTask) -> Any? in
if taskk.error != nil {
// Error.
} else {
// Do something with your result.
}
return nil
})
}
}
Thanks :)
We should use AWSS3TransferUtility now because AWSS3TransferManagerUploadRequest is deprecated, here is the jpeg upload function in Swift 4.2 but it can be easily changed for any data type:
func uploadS3(image: UIImage,
name: String,
progressHandler: #escaping (Progress) -> Void,
completionHandler: #escaping (Error?) -> Void) {
guard let data = UIImageJPEGRepresentation(image, Constants.uploadImageQuality) else {
DispatchQueue.main.async {
completionHandler(NetErrors.imageFormatError) // Replace your error
}
return
}
let credentialsProvider = AWSStaticCredentialsProvider(accessKey: Constants.accessKeyS3, secretKey: Constants.secretKeyS3)
let configuration = AWSServiceConfiguration(region: Constants.regionS3, credentialsProvider: credentialsProvider)
AWSServiceManager.default().defaultServiceConfiguration = configuration
let expression = AWSS3TransferUtilityUploadExpression()
expression.progressBlock = { task, progress in
DispatchQueue.main.async {
progressHandler(progress)
}
}
AWSS3TransferUtility.default().uploadData(
data,
bucket: Constants.bucketS3,
key: name,
contentType: "image/jpg",
expression: expression) { task, error in
DispatchQueue.main.async {
completionHandler(error)
}
print("Success")
}.continueWith { task -> AnyObject? in
if let error = task.error {
DispatchQueue.main.async {
completionHandler(error)
}
}
return nil
}
}
Do not forget to define or change Constants in the code. If you don't want to give public access, you should also define a user in IAM, and put this code in your bucket policy:
{
"Version": "2012-10-17",
"Id": "S3AccessPolicy",
"Statement": [
{
"Sid": "GiveAppAccess",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789012:user/YOUR_USER"
},
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Resource": "arn:aws:s3:::YOUR_BUCKET/*"
}
]
}
This is the latest code based on SWIFT 4 syntax
I am using the code of #Karthick Selvaraj.
I think now its help to other developers to understand new syntax
func uploadButtonPressed() {
if myimageView.image == nil {
// Do something to wake up user :)
} else {
let image = myimageView.image!
let fileManager = FileManager.default
let path = (NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString).appendingPathComponent("test3.jpeg")
let imageData = UIImageJPEGRepresentation(image, 0)
fileManager.createFile(atPath: path as String, contents: imageData, attributes: nil)
let fileUrl = NSURL(fileURLWithPath: path)
let uploadRequest = AWSS3TransferManagerUploadRequest()
uploadRequest?.bucket = "<Your Bucket Name>"
uploadRequest?.key = "<Image Name>"
uploadRequest?.contentType = "image/jpeg"
uploadRequest?.body = fileUrl as URL!
uploadRequest?.serverSideEncryption = AWSS3ServerSideEncryption.awsKms
uploadRequest?.uploadProgress = { (bytesSent, totalBytesSent, totalBytesExpectedToSend) -> Void in
DispatchQueue.main.async(execute: {
// print("totalBytesSent",totalBytesSent)
// print("totalBytesExpectedToSend",totalBytesExpectedToSend)
// self.amountUploaded = totalBytesSent // To show the updating data status in label.
// self.fileSize = totalBytesExpectedToSend
})
}
let transferManager = AWSS3TransferManager.default()
transferManager.upload(uploadRequest!).continueWith(executor: AWSExecutor.mainThread(), block: { (task:AWSTask<AnyObject>) -> Any? in
if task.error != nil {
// Error.
print("error")
} else {
// Do something with your result.
print("No error Upload Done")
}
return nil
})
}
}
Enjoy !!!
This is image uploading using AWS S3 bucket this below code i implemented image uploading from gallery to uploading
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject])
{
if(picker.sourceType == UIImagePickerControllerSourceType.PhotoLibrary)
{
selectedImageUrl = info[UIImagePickerControllerReferenceURL] as! NSURL
myImageViewC.image = info[UIImagePickerControllerOriginalImage] as? UIImage
myImageViewC.backgroundColor = UIColor.clearColor()
myImageViewC.contentMode = UIViewContentMode.ScaleAspectFit
self.dismissViewControllerAnimated(true, completion: nil)
startUploadingImage()
}
else if(picker.sourceType == UIImagePickerControllerSourceType.Camera)
{
myImageViewC.image = info[UIImagePickerControllerOriginalImage] as? UIImage
myImageViewC.backgroundColor = UIColor.clearColor()
myImageViewC.contentMode = UIViewContentMode.ScaleAspectFit
self.dismissViewControllerAnimated(true, completion: nil)
myActivityIndicator.startAnimating()
let S3BucketName = "streetsmartb2/sai"
let date3 = NSDate()
let timeInMi = "\(CLongLong((floor(date3.timeIntervalSince1970 * 1000))))"
let S3UploadKeyName = "File.jpg\(timeInMi)"
//print("value1:\(S3UploadKeyName)")
//settings temp location for image
let imageName = NSURL.fileURLWithPath(NSTemporaryDirectory() + S3UploadKeyName).lastPathComponent
let documentDirectory = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true).first! as String
// getting local path
let localPath = (documentDirectory as NSString).stringByAppendingPathComponent(imageName!)
//getting actual image
let image = info[UIImagePickerControllerOriginalImage] as! UIImage
//let data = UIImageJPEGRepresentation(image, 0.5)
let data = CreateTeamViewController().resizeImage(image)
data.writeToFile(localPath, atomically: true)
//let imageData = NSData(contentsOfFile: localPath)!
let photoURL = NSURL(fileURLWithPath: localPath)
let uploadRequest = AWSS3TransferManagerUploadRequest()
uploadRequest.body = photoURL
uploadRequest.key = S3UploadKeyName
uploadRequest.bucket = S3BucketName
uploadRequest.contentType = "image/jpeg"
let transferManager = AWSS3TransferManager.defaultS3TransferManager()
// Perform file upload
transferManager.upload(uploadRequest).continueWithBlock { (task) -> AnyObject! in
if let error = task.error {
print("Upload failed with error: (\(error.localizedDescription))")
dispatch_async(dispatch_get_main_queue()) {
// self.returnToAddView()
self.myActivityIndicator.stopAnimating()
CreateTeamViewController().displayAlertMessage("Error uploading Image")
}
}
if let exception = task.exception {
print("Upload failed with exception (\(exception))")
dispatch_async(dispatch_get_main_queue()) {
// self.returnToAddView()
self.myActivityIndicator.stopAnimating()
CreateTeamViewController().displayAlertMessage("Error uploading Image")
}
}
if task.result != nil {
// Remove locally stored file
self.remoteImageWithUrl(uploadRequest.key!)
let s3URL = NSURL(string: "https://s3.amazonaws.com/\(S3BucketName)/\(uploadRequest.key!)")!
// print("Uploaded to:\n\(s3URL)")
dispatch_async(dispatch_get_main_queue()) {
// self.returnToAddView()
self.myActivityIndicator.stopAnimating()
self.createTeamImageButton?.setImage(self.loadImage, forState: .Normal)
self.uploadedImageURL = (s3URL.URLString)
// self.teamImageNameCreate = self.uploadedImageURL
// self.createTeamImageButton.sd_setImageWithURL(NSURL(string: self.uploadedImageURL)!, forState: .Normal, placeholderImage: UIImage(named: "no_image_one.jpg"))
let url = NSURL.init(string: self.uploadedImageURL)
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
// do some task
let imagedata = NSData(contentsOfURL: url!)
if let imageObj = UIImage.init(data: imagedata!) {
self.createTeamPic = imageObj
}
dispatch_async(dispatch_get_main_queue()) {
self.createTeamImageButton?.setImage(self.createTeamPic, forState: .Normal)
}
}
}
}
else {
// print("Unexpected empty result.")
}
return nil
}
}
}