Files
suixinkan_uikit/suixinkan/Features/CloudDrive/Services/CloudTransferWorkers.swift

114 lines
3.8 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// CloudTransferWorkers.swift
// suixinkan
//
import Foundation
import Photos
/// OSS 便
@MainActor
protocol CloudDriveUploading {
/// URL
func uploadCloudDriveFile(
data: Data,
fileName: String,
fileType: Int,
scenicId: Int,
onProgress: @escaping (Int) -> Void
) async throws -> String
}
extension OSSUploadService: CloudDriveUploading {}
///
protocol CloudFileDownloading {
/// URL
func downloadFile(
remoteURL: String,
fileName: String,
onProgress: @escaping @Sendable (Int) -> Void
) async throws -> URL
}
/// URLSession
struct CloudURLSessionDownloader: CloudFileDownloading {
func downloadFile(
remoteURL: String,
fileName: String,
onProgress: @escaping @Sendable (Int) -> Void
) async throws -> URL {
guard let url = URL(string: remoteURL) else {
throw CloudTransferError.invalidURL
}
onProgress(1)
let (temporaryURL, _) = try await URLSession.shared.download(from: url)
try Task.checkCancellation()
let directory = FileManager.default.temporaryDirectory.appendingPathComponent("cloud_drive_downloads", isDirectory: true)
try FileManager.default.createDirectory(at: directory, withIntermediateDirectories: true)
let destinationURL = directory.appendingPathComponent(CloudTransferFileName.sanitized(fileName))
if FileManager.default.fileExists(atPath: destinationURL.path) {
try FileManager.default.removeItem(at: destinationURL)
}
try FileManager.default.moveItem(at: temporaryURL, to: destinationURL)
onProgress(100)
return destinationURL
}
}
///
protocol CloudPhotoSaving {
///
func saveToPhotoLibrary(fileURL: URL, fileType: Int) async throws
}
/// Photos
struct CloudPhotoLibrarySaver: CloudPhotoSaving {
func saveToPhotoLibrary(fileURL: URL, fileType: Int) async throws {
let status = await PHPhotoLibrary.requestAuthorization(for: .addOnly)
guard status == .authorized || status == .limited else {
throw CloudTransferError.photoPermissionDenied
}
try await PHPhotoLibrary.shared().performChanges {
if fileType == 1 {
PHAssetChangeRequest.creationRequestForAssetFromVideo(atFileURL: fileURL)
} else {
PHAssetChangeRequest.creationRequestForAssetFromImage(atFileURL: fileURL)
}
}
}
}
///
enum CloudTransferError: LocalizedError, Equatable {
case invalidURL
case localFileMissing
case photoPermissionDenied
var errorDescription: String? {
switch self {
case .invalidURL:
"文件地址不存在"
case .localFileMissing:
"本地文件不存在"
case .photoPermissionDenied:
"请允许访问相册后再下载"
}
}
}
///
enum CloudTransferFileName {
///
static func sanitized(_ fileName: String) -> String {
let trimmed = fileName.trimmingCharacters(in: .whitespacesAndNewlines)
var unsafe = CharacterSet.controlCharacters
unsafe.formUnion(CharacterSet(charactersIn: "/\\"))
let value = trimmed.unicodeScalars.reduce(into: "") { result, scalar in
result += unsafe.contains(scalar) ? "_" : String(scalar)
}
return value.isEmpty ? "cloud_file" : value
}
}