问题描述
从照片中选择文件时,iOS 13添加trim.
前缀:
iOS 13 adds a trim.
prefix when selecting a file from Photos:
file:///private/var/mobile/Containers/Data/PluginKitPlugin/FPDLKFHEQ-4T56-3456-HTE2-39EK2KDJUR/tmp/trim.DFLSPD0F-32RE-UYI8-DFHA-DPFLEOW098UH.MOV
在iOS-13之前,是这样的:
Before iOS-13 was like this:
file:///private/var/mobile/Containers/Data/PluginKitPlugin/FPDLKFHEQ-4T56-3456-HTE2-39EK2KDJUR/tmp/DFLSPD0F-32RE-UYI8-DFHA-DPFLEOW098UH.MOV
当将文件URL传递到alamofire以将文件上传到后端服务器时,这是一个问题.它导致未知错误",并且上传失败.也许alamofire在使用这个小前缀时遇到了麻烦?
This is an issue when passing the file URL to alamofire to upload the file to a backend server. It causes an "unknown error" and the upload fails. Perhaps alamofire is having trouble with that little prefix?
对此有什么解决办法吗?
Is there any solution for this?
推荐答案
是的,这里的人们遇到了同一问题 .我会扩展答案.
Yes, here people have faced the same issue. I will extend the answer.
您可能需要将该视频复制到临时文件夹中,因此请使用UIImagePickerControllerDelegate
的方法:
You probably need to copy that video into the temporary folder, so in your UIImagePickerControllerDelegate
's method:
public func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) {
if let mediaType = info[.mediaType] as? String,
mediaType == "public.movie",
let trimVideoURL = info[.mediaURL] as? URL {
if #available(iOS 13, *) {
// 1
let urlSlices = trimVideoURL.relativeString.split(separator: ".")
// 2
let tempDirectoryURL = URL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true)
// 3
let targetFileURL = tempDirectoryURL.appendingPathComponent(String(urlSlices[1])).appendingPathExtension(String(urlSlices[2]))
do {
// 4
try FileManager.default.copyItem(at: trimVideoURL, to: targetFileURL)
} catch {
print(error.localizedDescription)
}
// use the video file via targetFileURL path
}
}
}
-
这里有trimVideURL,需要用
.
进行切片file:///private/var/mobile/Containers/Data/PluginKitPlugin/ECD6D7FD-35A8-47E2-8323-808454A32C37/tmp/trim.919BDBB7-E711-49AA-BB84-89E9B0416045.MOV
创建临时目录:file:///private/var/mobile/Containers/Data/Application/FCD3E053-82DF-4EAE-86BA-4C65880D5B90/tmp/
Create temporary directory:file:///private/var/mobile/Containers/Data/Application/FCD3E053-82DF-4EAE-86BA-4C65880D5B90/tmp/
在临时文件夹中编写目标文件名:file:///private/var/mobile/Containers/Data/Application/FCD3E053-82DF-4EAE-86BA-4C65880D5B90/tmp/919BDBB7-E711-49AA-BB84-89E9B0416045.MOV
Compose the target filename in temporary folder: file:///private/var/mobile/Containers/Data/Application/FCD3E053-82DF-4EAE-86BA-4C65880D5B90/tmp/919BDBB7-E711-49AA-BB84-89E9B0416045.MOV
最后使用FileManager
准备就绪后,您可以使用以下方法删除文件:
And when you ready, you could delete the file using:
do {
try FileManager.default.removeItem(at: targetFileURL)
} catch {
print(error.localizedDescription)
}
此外,您可以将该测试项目用作参考,只需将其复制到新创建的项目中即可测试功能:
Also, you could use this test project as a reference, just copy it into new created project to test out functionality:
import UIKit
import WebKit
class ViewController: UIViewController, UINavigationControllerDelegate {
var imageView: UIImageView!
var videoView: WKWebView!
var selectButton: UIButton!
var deleteButton: UIButton!
var pickerController: UIImagePickerController?
var targetFileURL: URL?
override func viewDidLoad() {
super.viewDidLoad()
configureUI()
setupPickerController()
}
func configureUI() {
imageView = UIImageView()
imageView.translatesAutoresizingMaskIntoConstraints = false
videoView = WKWebView()
videoView.translatesAutoresizingMaskIntoConstraints = false
selectButton = UIButton(type: .system)
selectButton.setTitle("Select", for: .normal)
selectButton.addTarget(self, action: #selector(showImagePicker), for: .touchUpInside)
selectButton.translatesAutoresizingMaskIntoConstraints = false
deleteButton = UIButton(type: .system)
deleteButton.setTitle("Delete", for: .normal)
deleteButton.addTarget(self, action: #selector(deleteCurrentTempFile), for: .touchUpInside)
deleteButton.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(imageView)
view.addSubview(videoView)
view.addSubview(selectButton)
view.addSubview(deleteButton)
imageView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
imageView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
imageView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
imageView.heightAnchor.constraint(equalToConstant: 250.0).isActive = true
videoView.topAnchor.constraint(equalTo: imageView.bottomAnchor).isActive = true
videoView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
videoView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
videoView.heightAnchor.constraint(equalTo: imageView.heightAnchor).isActive = true
deleteButton.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
deleteButton.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
deleteButton.heightAnchor.constraint(equalToConstant: 60.0).isActive = true
deleteButton.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true
selectButton.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
selectButton.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
selectButton.heightAnchor.constraint(equalTo: deleteButton.heightAnchor).isActive = true
selectButton.bottomAnchor.constraint(equalTo: deleteButton.topAnchor).isActive = true
view.layoutIfNeeded()
}
func setupPickerController() {
self.pickerController = UIImagePickerController()
self.pickerController?.delegate = self
if let mediaTypes = UIImagePickerController.availableMediaTypes(for: .photoLibrary) {
self.pickerController?.mediaTypes = mediaTypes
}
}
private func action(for type: UIImagePickerController.SourceType, title: String) -> UIAlertAction? {
guard UIImagePickerController.isSourceTypeAvailable(type) else {
return nil
}
return UIAlertAction(title: title, style: .default) { [unowned self] _ in
self.pickerController?.sourceType = type
if let pickerController = self.pickerController {
self.present(pickerController, animated: true)
}
}
}
@IBAction func showImagePicker() {
let alertController = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
if let action = self.action(for: .photoLibrary, title: "Photo library") {
alertController.addAction(action)
}
alertController.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
present(alertController, animated: true)
}
@IBAction func deleteCurrentTempFile() {
if let url = targetFileURL,
FileManager.default.fileExists(atPath: url.path) {
removeTemporaryFile(at: url)
}
}
func didSelectMedia(image: UIImage?, videoURL: URL?) {
if let image = image {
imageView.image = image
} else if let videoURL = videoURL {
let request = URLRequest(url: videoURL)
videoView.load(request)
targetFileURL = videoURL
}
}
// remove it when you done
func removeTemporaryFile(at url: URL) {
do {
try FileManager.default.removeItem(at: url)
} catch {
print(error.localizedDescription)
}
targetFileURL = nil
}
}
extension ViewController: UIImagePickerControllerDelegate {
public func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) {
if let mediaType = info[.mediaType] as? String {
if mediaType == "public.movie", let trimVideoURL = info[.mediaURL] as? URL {
if #available(iOS 13, *) {
let urlSlices = trimVideoURL.relativeString.split(separator: ".")
let tempDirectoryURL = URL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true)
let targetFileURL = tempDirectoryURL.appendingPathComponent(String(urlSlices[1])).appendingPathExtension(String(urlSlices[2]))
do {
try FileManager.default.copyItem(at: trimVideoURL, to: targetFileURL)
} catch {
print(error.localizedDescription)
}
self.didSelectMedia(image: nil, videoURL: targetFileURL)
} else {
self.didSelectMedia(image: nil, videoURL: trimVideoURL)
}
} else if mediaType == "public.image", let image = info[.originalImage] as? UIImage {
self.didSelectMedia(image: image, videoURL: nil)
}
}
picker.dismiss(animated: true, completion: nil)
}
}
这篇关于iOS 13添加了“修剪".从UIImagePickController选择的文件的前缀的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!