具有共享扩展名的后台上传

我创建了一个macOS ShareExtension,可以用来上传图片。

我仍在测试,因此所有请求都将发送到https://beeceptor.com

共享扩展名运行良好,并在运行后显示在预览中:

股份延伸

我添加一些文字,然后点击“发布”

创建帖子

但是图像然后没有上传。这是我的代码,用于启动后台上传:

let sc_uploadURL = "https://xyz.free.beeceptor.com/api/posts" // https://beeceptor.com/console/xyz

override func didSelectPost() {
    // This is called after the user selects Post. Do the upload of contentText and/or NSExtensionContext attachments.
    let configName = "com.shinobicontrols.ShareAlike.BackgroundSessionConfig"
    let sessionConfig = URLSessionConfiguration.background(withIdentifier: configName)
    // Extensions aren't allowed their own cache disk space. Need to share with application
    sessionConfig.sharedContainerIdentifier = "group.CreateDaily"
    let session = URLSession(configuration: sessionConfig)

    // Prepare the URL Request
    let request = urlRequestWithImage(image: attachedImage, text: contentText)

    // Create the task, and kick it off
    let task = session.dataTask(with: request! as URLRequest)
    task.resume()

    // Inform the host that we're done, so it un-blocks its UI. Note: Alternatively you could call super's -didSelectPost, which will similarly complete the extension context.
    extensionContext?.completeRequest(returningItems: [AnyObject](), completionHandler: nil)
}

private func urlRequestWithImage(image: NSImage?, text: String) -> NSURLRequest? {
    let url = URL(string: sc_uploadURL)!
    let request: NSMutableURLRequest? =  NSMutableURLRequest(url: url as URL)
    request?.addValue("application/json", forHTTPHeaderField: "Content-Type")
    request?.addValue("application/json", forHTTPHeaderField: "Accept")
    request?.httpMethod = "POST"

    let jsonObject = NSMutableDictionary()
    jsonObject["text"] = text
    if let image = image {
        jsonObject["image_details"] = extractDetailsFromImage(image: image)
    }

    // Create the JSON payload
    let jsonData = try! JSONSerialization.data(withJSONObject: jsonObject, options: JSONSerialization.WritingOptions.prettyPrinted)
    request?.httpBody = jsonData
    return request
}

请注意,sharedContainerIdentifier应用程序的权利以及共享扩展的权利中均包含。

共享容器

ShareExtensions位于相应的应用程序组中,并且启用了传出连接。

应用程序组和网络

库西奇

执行后台上传

Once the user has completed their entry, and clicks the Post button, then the extension should upload the content to some web service somewhere. For the purposes of this example, the URL of the endpoint is contained within a property on the view controller:

let sc_uploadURL = "http://requestb.in/oha28noh"

This is a URL for the Request Bin service, which gives you a temporary URL to allow you to test network operations. The above URL (and the one in the sample code) won’t work for you, but if you visit requestb.in then you can get hold of your own URL for testing.

As mentioned previously, it’s important that extensions put very little strain on the limited system resources. Therefore, at the point the Post button is tapped, there is no time to perform a synchronous, foreground network operation. Luckily, NSURLSession provides a simple API for creating background network operations, and that’s what you’ll need here.

The method which gets called when the user taps post is didSelectPost(), and in its simplest form it must look like this:

override func didSelectPost() {
  // Perform upload
  ...

  // Inform the host that we're done, so it un-blocks its UI.
  extensionContext?.completeRequestReturningItems(nil, completionHandler: nil)
}

Setting up an NSURLSession is pretty standard:

let configName = "com.shinobicontrols.ShareAlike.BackgroundSessionConfig"
let sessionConfig = NSURLSessionConfiguration.backgroundSessionConfigurationWithIdentifier(configName)
// Extensions aren't allowed their own cache disk space. Need to share with application
sessionConfig.sharedContainerIdentifier = "group.ShareAlike"
let session = NSURLSession(configuration: sessionConfig)

The important part to note of the above code segment is the line which sets the sharedContainerIdentifier on the session configuration. This specifies the name of the container that NSURLSession can use as a cache (since extensions don’t have their own writable disc access). This container needs to be set up as part of the host application (i.e. ShareAlike in this demo), and can be done through Xcode:

  1. Go to the capabilities tab of the app’s target
  2. Enable App Groups
  3. Create a new app group, entitled something appropriate. It must start with group.. In the demo the group is called group.ShareAlike
  4. Let Xcode go through the process of creating this group for you.

在此处输入图片说明

Then you need to go to the extension’s target, and follow the same process. Note that you won’t need to create a new app group, but instead select the one that you created for your host application.

在此处输入图片说明

These app groups are registered against your developer ID, and the signing process ensures that only your apps are able to access these shared containers.

Xcode will have created an entitlements file for each of your projects, and this will contain the name of the shared container it has access to.

Now that you’ve got your session set up correctly, you need to create a URL request to perform:

// Prepare the URL Request
let request = urlRequestWithImage(attachedImage, text: contentText)

This calls a method which constructs a URL request which uses HTTP POST to send some JSON, which includes the string content, and some metadata properties about the image:

func urlRequestWithImage(image: UIImage?, text: String) -> NSURLRequest? {
  let url = NSURL.URLWithString(sc_uploadURL)
  let request = NSMutableURLRequest(URL: url)
  request.addValue("application/json", forHTTPHeaderField: "Content-Type")
  request.addValue("application/json", forHTTPHeaderField: "Accept")
  request.HTTPMethod = "POST"

  var jsonObject = NSMutableDictionary()
  jsonObject["text"] = text
  if let image = image {
    jsonObject["image_details"] = extractDetailsFromImage(image)
  }

  // Create the JSON payload
  var jsonError: NSError?
  let jsonData = NSJSONSerialization.dataWithJSONObject(jsonObject, options: nil, error: &jsonError)
  if jsonData {
    request.HTTPBody = jsonData
  } else {
    if let error = jsonError {
      println("JSON Error: \(error.localizedDescription)")
    }
  }

  return request
}

This method doesn’t actually create a request which uploads the image, although it could be adapted to do so. Instead, it extracts some details about the image using the following method:

func extractDetailsFromImage(image: UIImage) -> NSDictionary {
  var resultDict = [String : AnyObject]()
  resultDict["height"] = image.size.height
  resultDict["width"] = image.size.width
  resultDict["orientation"] = image.imageOrientation.toRaw()
  resultDict["scale"] = image.scale
  resultDict["description"] = image.description
  return resultDict
}

最后,您可以要求会话创建与您所建立的请求相关联的任务,然后在其上调用resume()以在后台启动它:

// Create the task, and kick it off
let task = session.dataTaskWithRequest(request!)
task.resume()

如果您现在执行此过程,并使用自己的requestb.in URL,则可以期望看到如下结果:

在此处输入图片说明

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

NSUserDefaults不保存到具有共享扩展名的磁盘

Azure - 具有给定扩展名的文件共享中的文件

Python Webhook用于下载和上传具有不同扩展名的文件

使用ajax和flask上传具有不同扩展名的文件

如何在具有特定ID的歌剧库中上传CRX / NEX扩展名?

上传具有不同扩展名的多个文件 firebase 存储

从共享扩展名上传iOS照片,上传完成后响应

防止Facebook上传带有chrome扩展名的图像

WinSCP递归查找具有特定扩展名的所有文件,并将其上传到FTP服务器

从具有多个扩展名的文件名中删除某些扩展名

glob语法以匹配具有任何扩展名或没有扩展名的文件

提取具有扩展名URL的文件名

在 Javascript/FileApi 中上传文件时,如何检查文件是否具有所需的扩展名

从具有相同名称但不同扩展名的文件(*.pdf 和 *.rtf),如果 *.rtf 是较新的,则在控制台上输出消息

具有进度块的Amazon S3 iOS SDK后台上传

文件具有tmp扩展名时确定Perl中的视频扩展名

获取具有特定扩展名的所有文件

如何从上传的图片中获取文件扩展名,而文件名中没有扩展名

从多个目录复制具有特定扩展名的文件

复制具有多个扩展名的文件

打印具有特定扩展名的文件

查找具有某些扩展名的文件

递归查找具有某些扩展名的图像

查找具有特定扩展名的文件

使用具有多个扩展名的endswith

使用scp复制具有某些扩展名的文件

在MacOS中同步具有不同扩展名的文件

如何重命名具有不同扩展名的文件

Labview:删除具有相同扩展名的文件