feat: tired
This commit is contained in:
parent
599ea6eae7
commit
df82849352
Binary file not shown.
@ -3,27 +3,6 @@ import Foundation
|
||||
/// API 配置信息
|
||||
public enum APIConfig {
|
||||
/// API 基础 URL
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
public static let baseURL = "https://api-dev.memorywake.com:31274/api/v1"
|
||||
|
||||
/// 获取认证token
|
||||
public static var authToken: String {
|
||||
let token = KeychainHelper.getAccessToken() ?? ""
|
||||
if token.isEmpty {
|
||||
print("⚠️ [APIConfig] 未找到访问令牌")
|
||||
}
|
||||
return token
|
||||
}
|
||||
|
||||
=======
|
||||
public static let baseURL = "https://api.memorywake.com/api/v1"
|
||||
|
||||
/// 认证 token - 生产环境中应该存储在 Keychain 中
|
||||
public static let authToken = "eyJ0eXAiOiJKV1QiLCJhbGciOiJFZERTQSJ9.eyJqdGkiOjczNjM0ODY2MTE1MDc2NDY0NjQsImlkZW50aXR5IjoiNzM1MDQzOTY2MzExNjYxOTg4OCIsImV4cCI6MTc1NjE5NjgxNX0.hRC_So6LHuR6Gx-bDyO8aliVOd-Xumul8M7cydi2pTxHPweBx4421AfZ5BjGoEEwRZPIXJ5z7a1aDB7qvjpLCA"
|
||||
|
||||
>>>>>>> a207b78 (feat: 确认上传)
|
||||
=======
|
||||
public static let baseURL = "https://api-dev.memorywake.com:31274/api/v1"
|
||||
|
||||
/// 认证 token - 从 Keychain 中获取
|
||||
@ -37,7 +16,6 @@ public enum APIConfig {
|
||||
return token
|
||||
}
|
||||
|
||||
>>>>>>> 1814789 (feat: 登录接口联调)
|
||||
/// 认证请求头
|
||||
public static var authHeaders: [String: String] {
|
||||
let token = authToken
|
||||
@ -52,12 +30,5 @@ public enum APIConfig {
|
||||
|
||||
return headers
|
||||
}
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
|
||||
}
|
||||
=======
|
||||
}
|
||||
>>>>>>> a207b78 (feat: 确认上传)
|
||||
=======
|
||||
}
|
||||
>>>>>>> 1814789 (feat: 登录接口联调)
|
||||
|
||||
@ -1,320 +1,17 @@
|
||||
import SwiftUI
|
||||
import PhotosUI
|
||||
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
// MARK: - Photo Picker
|
||||
=======
|
||||
/// 上传管理器,处理图片上传
|
||||
/// 图片上传管理器
|
||||
class ImageUploader: ObservableObject {
|
||||
private let baseURL = "https://api.memorywake.com/api/v1/file/generate-upload-url"
|
||||
|
||||
func uploadImage(_ image: UIImage, completion: @escaping (Result<String, Error>) -> Void) {
|
||||
print("🔄 开始准备上传图片...")
|
||||
// 1. 将图片转换为Data
|
||||
guard let imageData = image.jpegData(compressionQuality: 0.7) else {
|
||||
let error = NSError(domain: "ImageError", code: -1, userInfo: [NSLocalizedDescriptionKey: "图片数据转换失败"])
|
||||
print("❌ 错误:\(error.localizedDescription)")
|
||||
completion(.failure(error))
|
||||
return
|
||||
}
|
||||
|
||||
// 2. 检查URL是否有效
|
||||
guard let url = URL(string: baseURL) else {
|
||||
let error = NSError(domain: "URLError", code: -1, userInfo: [NSLocalizedDescriptionKey: "无效的URL"])
|
||||
print("❌ 错误:\(error.localizedDescription)")
|
||||
completion(.failure(error))
|
||||
return
|
||||
}
|
||||
|
||||
var request = URLRequest(url: url)
|
||||
request.httpMethod = "POST"
|
||||
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
|
||||
request.setValue("application/json", forHTTPHeaderField: "Accept")
|
||||
request.setValue("Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJFZERTQSJ9.eyJqdGkiOjczNjM0ODY2MTE1MDc2NDY0NjQsImlkZW50aXR5IjoiNzM1MDQzOTY2MzExNjYxOTg4OCIsImV4cCI6MTc1NjE5NjgxNX0.hRC_So6LHuR6Gx-bDyO8aliVOd-Xumul8M7cydi2pTxHPweBx4421AfZ5BjGoEEwRZPIXJ5z7a1aDB7qvjpLCA", forHTTPHeaderField: "Authorization")
|
||||
|
||||
// 3. 准备请求参数
|
||||
let fileName = "avatar_\(UUID().uuidString).jpg"
|
||||
let parameters: [String: Any] = [
|
||||
"filename": fileName,
|
||||
"content_type": "image/jpeg",
|
||||
"file_size": imageData.count
|
||||
]
|
||||
|
||||
do {
|
||||
request.httpBody = try JSONSerialization.data(withJSONObject: parameters)
|
||||
print("📤 准备上传请求,文件名: \(fileName), 大小: \(Double(imageData.count) / 1024.0) KB")
|
||||
print("📡 请求参数: \(parameters)")
|
||||
} catch {
|
||||
print("❌ 序列化请求参数失败: \(error.localizedDescription)")
|
||||
completion(.failure(error))
|
||||
return
|
||||
}
|
||||
|
||||
// 4. 打印调试信息
|
||||
print("🌐 请求URL: \(url.absoluteString)")
|
||||
print("📋 请求头: \(request.allHTTPHeaderFields ?? [:])")
|
||||
|
||||
// 5. 发起获取上传URL的请求
|
||||
print("🌐 正在获取上传链接...")
|
||||
let task = URLSession.shared.dataTask(with: request) { [weak self] data, response, error in
|
||||
// 切换到主线程处理响应
|
||||
DispatchQueue.main.async {
|
||||
if let error = error {
|
||||
print("❌ 请求失败: \(error.localizedDescription)")
|
||||
completion(.failure(error))
|
||||
return
|
||||
}
|
||||
|
||||
guard let httpResponse = response as? HTTPURLResponse else {
|
||||
let error = NSError(domain: "NetworkError", code: -1, userInfo: [NSLocalizedDescriptionKey: "无效的服务器响应"])
|
||||
print("❌ 错误:\(error.localizedDescription)")
|
||||
completion(.failure(error))
|
||||
return
|
||||
}
|
||||
|
||||
print("📊 响应状态码: \(httpResponse.statusCode)")
|
||||
print("📦 响应头: \(httpResponse.allHeaderFields)")
|
||||
|
||||
guard let data = data else {
|
||||
let error = NSError(domain: "NetworkError", code: -1, userInfo: [NSLocalizedDescriptionKey: "没有接收到数据"])
|
||||
print("❌ 错误:\(error.localizedDescription)")
|
||||
completion(.failure(error))
|
||||
return
|
||||
}
|
||||
|
||||
// 打印原始响应数据
|
||||
if let responseString = String(data: data, encoding: .utf8) {
|
||||
print("📡 原始响应数据: \(responseString)")
|
||||
}
|
||||
|
||||
// 5. 解析获取上传URL的响应
|
||||
do {
|
||||
guard let json = try JSONSerialization.jsonObject(with: data) as? [String: Any] else {
|
||||
throw NSError(domain: "ParseError", code: -1, userInfo: [NSLocalizedDescriptionKey: "响应数据格式错误"])
|
||||
}
|
||||
|
||||
print("📋 解析后的JSON: \(json)")
|
||||
|
||||
// 根据实际API响应结构调整这里的键名
|
||||
if let uploadUrlString = json["url"] as? String,
|
||||
let uploadUrl = URL(string: uploadUrlString) {
|
||||
print("✅ 成功获取上传链接: \(uploadUrlString)")
|
||||
self?.uploadImageData(imageData, to: uploadUrl, fileName: fileName, completion: completion)
|
||||
} else {
|
||||
throw NSError(domain: "APIError", code: -1, userInfo: [NSLocalizedDescriptionKey: "无法获取上传链接: \(json)"])
|
||||
}
|
||||
} catch {
|
||||
print("❌ 解析响应数据失败: \(error.localizedDescription)")
|
||||
completion(.failure(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
task.resume()
|
||||
}
|
||||
|
||||
private func uploadImageData(_ data: Data, to url: URL, fileName: String, completion: @escaping (Result<String, Error>) -> Void) {
|
||||
var request = URLRequest(url: url)
|
||||
request.httpMethod = "PUT"
|
||||
request.setValue("image/jpeg", forHTTPHeaderField: "Content-Type")
|
||||
request.httpBody = data
|
||||
|
||||
print("🚀 开始上传图片数据...")
|
||||
|
||||
let task = URLSession.shared.dataTask(with: request) { _, response, error in
|
||||
DispatchQueue.main.async {
|
||||
if let error = error {
|
||||
print("❌ 上传失败: \(error.localizedDescription)")
|
||||
completion(.failure(error))
|
||||
return
|
||||
}
|
||||
|
||||
// 处理上传响应
|
||||
if let httpResponse = response as? HTTPURLResponse {
|
||||
print("📊 上传响应状态码: \(httpResponse.statusCode)")
|
||||
|
||||
if (200...299).contains(httpResponse.statusCode) {
|
||||
let fileUrl = "https://your-cdn-domain.com/\(fileName)" // 替换为实际的CDN域名
|
||||
print("✅ 上传成功!文件URL: \(fileUrl)")
|
||||
completion(.success(fileUrl))
|
||||
} else {
|
||||
let errorMessage = "上传失败,状态码: \(httpResponse.statusCode)"
|
||||
print("❌ \(errorMessage)")
|
||||
let error = NSError(domain: "UploadError",
|
||||
code: httpResponse.statusCode,
|
||||
userInfo: [NSLocalizedDescriptionKey: errorMessage])
|
||||
completion(.failure(error))
|
||||
}
|
||||
} else {
|
||||
let errorMessage = "无效的服务器响应"
|
||||
print("❌ \(errorMessage)")
|
||||
let error = NSError(domain: "UploadError",
|
||||
code: -1,
|
||||
userInfo: [NSLocalizedDescriptionKey: errorMessage])
|
||||
completion(.failure(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
task.resume()
|
||||
}
|
||||
}
|
||||
>>>>>>> a4890a4 (feat: 图片上传互获取url)
|
||||
|
||||
=======
|
||||
>>>>>>> a207b78 (feat: 确认上传)
|
||||
=======
|
||||
/// 上传结果,包含原图和压缩图的上传信息
|
||||
struct UploadResults {
|
||||
let original: ImageUploaderGetID.UploadResult
|
||||
let compressed: ImageUploaderGetID.UploadResult
|
||||
}
|
||||
|
||||
>>>>>>> 5611df8 (feat: 素材上传成)
|
||||
=======
|
||||
// MARK: - Data Models
|
||||
|
||||
/// 上传进度信息
|
||||
public struct UploadProgress {
|
||||
public let current: Int
|
||||
public let total: Int
|
||||
public let progress: Double
|
||||
public let isOriginal: Bool
|
||||
|
||||
public init(current: Int, total: Int, progress: Double, isOriginal: Bool) {
|
||||
self.current = current
|
||||
self.total = total
|
||||
self.progress = progress
|
||||
self.isOriginal = isOriginal
|
||||
}
|
||||
}
|
||||
|
||||
/// 上传结果,包含原图和压缩图的上传信息
|
||||
public struct UploadResults {
|
||||
public let original: ImageUploaderGetID.UploadResult
|
||||
public let compressed: ImageUploaderGetID.UploadResult
|
||||
|
||||
public init(original: ImageUploaderGetID.UploadResult,
|
||||
compressed: ImageUploaderGetID.UploadResult) {
|
||||
self.original = original
|
||||
self.compressed = compressed
|
||||
}
|
||||
}
|
||||
|
||||
=======
|
||||
>>>>>>> 5edee64 (feat: 文件上传成功)
|
||||
// MARK: - Photo Picker
|
||||
|
||||
>>>>>>> 8e641fd (feat: 上传进度)
|
||||
/// 照片选择器,封装了系统相册选择功能
|
||||
struct PhotoPicker: UIViewControllerRepresentable {
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
// MARK: - Properties
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
|
||||
/// 绑定的已选图片数组,用于存储用户选择的图片
|
||||
>>>>>>> a207b78 (feat: 确认上传)
|
||||
=======
|
||||
>>>>>>> 8e641fd (feat: 上传进度)
|
||||
@Binding var selectedImages: [UIImage]
|
||||
let selectionLimit: Int
|
||||
let filter: PHPickerFilter
|
||||
<<<<<<< HEAD
|
||||
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
/// 图片上传管理器
|
||||
private let uploader = ImageUploader()
|
||||
=======
|
||||
/// 图片上传完成回调,返回上传结果或错误
|
||||
<<<<<<< HEAD
|
||||
var onImageUploaded: ((Result<ImageUploaderGetID.UploadResult, Error>) -> Void)?
|
||||
>>>>>>> a207b78 (feat: 确认上传)
|
||||
=======
|
||||
var onImageUploaded: ((Result<UploadResults, Error>) -> Void)?
|
||||
>>>>>>> 5611df8 (feat: 素材上传成)
|
||||
|
||||
// MARK: - Initialization
|
||||
|
||||
/// 初始化照片选择器
|
||||
<<<<<<< HEAD
|
||||
>>>>>>> a4890a4 (feat: 图片上传互获取url)
|
||||
init(selectedImages: Binding<[UIImage]>, selectionLimit: Int = 1, filter: PHPickerFilter = .images) {
|
||||
=======
|
||||
/// - Parameters:
|
||||
/// - selectedImages: 绑定的图片数组,用于接收用户选择的图片
|
||||
/// - selectionLimit: 最多可选图片数量,默认为1
|
||||
/// - filter: 媒体类型过滤器,默认为图片
|
||||
/// - onImageUploaded: 图片上传完成后的回调闭包
|
||||
init(
|
||||
selectedImages: Binding<[UIImage]>,
|
||||
selectionLimit: Int = 1,
|
||||
filter: PHPickerFilter = .images,
|
||||
onImageUploaded: ((Result<UploadResults, Error>) -> Void)? = nil
|
||||
) {
|
||||
>>>>>>> a207b78 (feat: 确认上传)
|
||||
=======
|
||||
var onImageUploaded: ((Result<UploadResults, Error>) -> Void)?
|
||||
var onUploadProgress: ((UploadProgress) -> Void)?
|
||||
=======
|
||||
|
||||
@Binding var selectedImages: [UIImage]
|
||||
let selectionLimit: Int
|
||||
let filter: PHPickerFilter
|
||||
var onImageUploaded: ((Result<ImageUploadService.UploadResults, Error>) -> Void)?
|
||||
var onUploadProgress: ((ImageUploadService.UploadProgress) -> Void)?
|
||||
@Environment(\.presentationMode) private var presentationMode
|
||||
>>>>>>> 5edee64 (feat: 文件上传成功)
|
||||
|
||||
// MARK: - Initialization
|
||||
|
||||
init(selectedImages: Binding<[UIImage]>,
|
||||
selectionLimit: Int = 1,
|
||||
filter: PHPickerFilter = .images,
|
||||
<<<<<<< HEAD
|
||||
onImageUploaded: ((Result<UploadResults, Error>) -> Void)? = nil,
|
||||
onUploadProgress: ((UploadProgress) -> Void)? = nil) {
|
||||
>>>>>>> 8e641fd (feat: 上传进度)
|
||||
=======
|
||||
onImageUploaded: ((Result<ImageUploadService.UploadResults, Error>) -> Void)? = nil,
|
||||
onUploadProgress: ((ImageUploadService.UploadProgress) -> Void)? = nil) {
|
||||
>>>>>>> 5edee64 (feat: 文件上传成功)
|
||||
self._selectedImages = selectedImages
|
||||
self.selectionLimit = selectionLimit
|
||||
self.filter = filter
|
||||
self.onImageUploaded = onImageUploaded
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
>>>>>>> 8e641fd (feat: 上传进度)
|
||||
self.onUploadProgress = onUploadProgress
|
||||
}
|
||||
|
||||
// MARK: - UIViewControllerRepresentable
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
|
||||
// MARK: - UIViewControllerRepresentable 协议方法
|
||||
=======
|
||||
}
|
||||
|
||||
// MARK: - UIViewControllerRepresentable
|
||||
>>>>>>> a207b78 (feat: 确认上传)
|
||||
|
||||
/// 创建并返回配置好的PHPickerViewController
|
||||
=======
|
||||
>>>>>>> 8e641fd (feat: 上传进度)
|
||||
=======
|
||||
|
||||
>>>>>>> 5edee64 (feat: 文件上传成功)
|
||||
func makeUIViewController(context: Context) -> PHPickerViewController {
|
||||
var configuration = PHPickerConfiguration(photoLibrary: PHPhotoLibrary.shared())
|
||||
configuration.filter = filter
|
||||
@ -332,337 +29,59 @@ struct PhotoPicker: UIViewControllerRepresentable {
|
||||
Coordinator(self)
|
||||
}
|
||||
|
||||
// MARK: - Coordinator
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
|
||||
// MARK: - 协调器类
|
||||
=======
|
||||
>>>>>>> a207b78 (feat: 确认上传)
|
||||
|
||||
/// 协调器类,处理PHPickerViewController的代理方法
|
||||
=======
|
||||
>>>>>>> 8e641fd (feat: 上传进度)
|
||||
class Coordinator: NSObject, PHPickerViewControllerDelegate {
|
||||
let parent: PhotoPicker
|
||||
<<<<<<< HEAD
|
||||
private let uploadService = ImageUploadService.shared
|
||||
|
||||
/// 图片上传器实例
|
||||
=======
|
||||
>>>>>>> 8e641fd (feat: 上传进度)
|
||||
private let uploader = ImageUploaderGetID()
|
||||
=======
|
||||
|
||||
class Coordinator: NSObject, PHPickerViewControllerDelegate {
|
||||
let parent: PhotoPicker
|
||||
private let uploadService = ImageUploadService.shared
|
||||
>>>>>>> 5edee64 (feat: 文件上传成功)
|
||||
|
||||
init(_ parent: PhotoPicker) {
|
||||
self.parent = parent
|
||||
}
|
||||
|
||||
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
|
||||
guard !results.isEmpty else {
|
||||
parent.presentationMode.wrappedValue.dismiss()
|
||||
return
|
||||
}
|
||||
|
||||
parent.selectedImages.removeAll()
|
||||
|
||||
let group = DispatchGroup()
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
var loadedImages: [Int: UIImage] = [:]
|
||||
var uploadResults: [Int: ImageUploadService.UploadResults] = [:]
|
||||
var lastError: Error?
|
||||
=======
|
||||
var loadedImages: [Int: UIImage] = [:] // 用于保持图片顺序的字典
|
||||
<<<<<<< HEAD
|
||||
>>>>>>> a207b78 (feat: 确认上传)
|
||||
=======
|
||||
var uploadResults: [Int: (original: ImageUploaderGetID.UploadResult?,
|
||||
compressed: ImageUploaderGetID.UploadResult?)] = [:]
|
||||
>>>>>>> 5611df8 (feat: 素材上传成)
|
||||
=======
|
||||
var loadedImages: [Int: UIImage] = [:]
|
||||
var uploadResults: [Int: (original: ImageUploaderGetID.UploadResult?,
|
||||
compressed: ImageUploaderGetID.UploadResult?)] = [:]
|
||||
>>>>>>> 8e641fd (feat: 上传进度)
|
||||
=======
|
||||
var loadedImages: [Int: UIImage] = [:]
|
||||
var uploadResults: [Int: ImageUploadService.UploadResults] = [:]
|
||||
var lastError: Error?
|
||||
>>>>>>> 5edee64 (feat: 文件上传成功)
|
||||
|
||||
for (index, result) in results.enumerated() {
|
||||
group.enter()
|
||||
|
||||
if result.itemProvider.canLoadObject(ofClass: UIImage.self) {
|
||||
<<<<<<< HEAD
|
||||
result.itemProvider.loadObject(ofClass: UIImage.self) { [weak self] (image, error) in
|
||||
<<<<<<< HEAD
|
||||
if let image = image as? UIImage {
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
// 将加载的图片存入字典,保持原始顺序
|
||||
>>>>>>> a207b78 (feat: 确认上传)
|
||||
loadedImages[index] = image
|
||||
=======
|
||||
guard let self = self, let image = image as? UIImage else {
|
||||
=======
|
||||
result.itemProvider.loadObject(ofClass: UIImage.self) { (image, error) in
|
||||
if let error = error {
|
||||
lastError = error
|
||||
group.leave()
|
||||
return
|
||||
if let image = image as? UIImage {
|
||||
loadedImages[index] = image
|
||||
}
|
||||
|
||||
guard let image = image as? UIImage else {
|
||||
lastError = NSError(domain: "com.wake.upload", code: -2, userInfo: [NSLocalizedDescriptionKey: "Failed to load image"])
|
||||
>>>>>>> 5edee64 (feat: 文件上传成功)
|
||||
group.leave()
|
||||
return
|
||||
}
|
||||
|
||||
loadedImages[index] = image
|
||||
|
||||
<<<<<<< HEAD
|
||||
guard let compressedImage = image.jpegData(compressionQuality: 0.5).flatMap(UIImage.init(data:)) else {
|
||||
group.leave()
|
||||
return
|
||||
}
|
||||
|
||||
<<<<<<< HEAD
|
||||
// 3. 上传原图
|
||||
self.uploader.uploadImage(image) { [weak self] originalResult in
|
||||
guard let self = self else {
|
||||
group.leave()
|
||||
return
|
||||
}
|
||||
>>>>>>> 5611df8 (feat: 素材上传成)
|
||||
|
||||
switch originalResult {
|
||||
case .success(let originalUploadResult):
|
||||
// 4. 原图上传成功后上传压缩图
|
||||
self.uploader.uploadImage(compressedImage) { compressedResult in
|
||||
defer { group.leave() }
|
||||
|
||||
switch compressedResult {
|
||||
case .success(let compressedUploadResult):
|
||||
// 保存两个上传结果
|
||||
uploadResults[index] = (originalUploadResult, compressedUploadResult)
|
||||
print("✅ 原图和压缩图上传成功!")
|
||||
print("📂 原图信息:")
|
||||
print(" - 文件ID: \(originalUploadResult.fileId)")
|
||||
print(" - 文件大小: \(originalUploadResult.fileSize) 字节")
|
||||
print("📦 压缩图信息:")
|
||||
print(" - 文件ID: \(compressedUploadResult.fileId)")
|
||||
print(" - 文件大小: \(compressedUploadResult.fileSize) 字节")
|
||||
|
||||
// 使用MaterialService上传文件信息到后端
|
||||
MaterialService.shared.uploadMaterialInfo(
|
||||
fileId: originalUploadResult.fileId,
|
||||
previewFileId: compressedUploadResult.fileId
|
||||
) { success, errorMessage in
|
||||
if success {
|
||||
print("✅ 文件信息上传成功 素材上传成功!!!!!")
|
||||
} else if let errorMessage = errorMessage {
|
||||
print("❌ 文件信息上传失败: \(errorMessage)")
|
||||
}
|
||||
}
|
||||
|
||||
case .failure(let error):
|
||||
print("❌ 压缩图上传失败: \(error.localizedDescription)")
|
||||
uploadResults[index] = (originalUploadResult, nil)
|
||||
}
|
||||
=======
|
||||
self.uploader.uploadImage(
|
||||
=======
|
||||
// Upload the image
|
||||
self.uploadService.uploadOriginalAndCompressedImage(
|
||||
>>>>>>> 5edee64 (feat: 文件上传成功)
|
||||
image,
|
||||
compressionQuality: 0.5,
|
||||
progress: { progress in
|
||||
DispatchQueue.main.async {
|
||||
self.parent.onUploadProgress?(progress)
|
||||
}
|
||||
},
|
||||
<<<<<<< HEAD
|
||||
completion: { [weak self] originalResult in
|
||||
guard let self = self else {
|
||||
group.leave()
|
||||
return
|
||||
>>>>>>> 8e641fd (feat: 上传进度)
|
||||
}
|
||||
=======
|
||||
completion: { result in
|
||||
defer { group.leave() }
|
||||
>>>>>>> 5edee64 (feat: 文件上传成功)
|
||||
|
||||
switch result {
|
||||
case .success(let results):
|
||||
uploadResults[index] = results
|
||||
|
||||
// 使用 NetworkService 上传文件信息
|
||||
let parameters: [String: Any] = [
|
||||
"file_id": results.original.fileId,
|
||||
"preview_file_id": results.compressed.fileId
|
||||
]
|
||||
|
||||
// 将参数包装在数组中
|
||||
let requestBody: [[String: Any]] = [parameters]
|
||||
|
||||
// 定义响应模型
|
||||
struct MaterialResponse: Decodable {
|
||||
let success: Bool
|
||||
let message: String?
|
||||
}
|
||||
|
||||
// 直接使用 URLSession 发送请求,确保数据格式正确
|
||||
do {
|
||||
let jsonData = try JSONSerialization.data(withJSONObject: requestBody)
|
||||
var request = URLRequest(url: URL(string: "\(APIConfig.baseURL)/material")!)
|
||||
request.httpMethod = "POST"
|
||||
request.allHTTPHeaderFields = APIConfig.authHeaders
|
||||
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
|
||||
request.httpBody = jsonData
|
||||
|
||||
let task = URLSession.shared.dataTask(with: request) { data, response, error in
|
||||
if let error = error {
|
||||
print("❌ 文件信息上传失败: \(error.localizedDescription)")
|
||||
return
|
||||
}
|
||||
|
||||
if let httpResponse = response as? HTTPURLResponse {
|
||||
if (200...299).contains(httpResponse.statusCode) {
|
||||
print("✅ 文件信息上传成功")
|
||||
} else {
|
||||
let statusCode = httpResponse.statusCode
|
||||
let errorMessage = String(data: data ?? Data(), encoding: .utf8) ?? ""
|
||||
print("❌ 服务器返回错误状态码: \(statusCode), 响应: \(errorMessage)")
|
||||
}
|
||||
}
|
||||
}
|
||||
task.resume()
|
||||
} catch {
|
||||
print("❌ 请求数据序列化失败: \(error.localizedDescription)")
|
||||
}
|
||||
|
||||
case .failure(let error):
|
||||
lastError = error
|
||||
print("❌ 图片上传失败: \(error.localizedDescription)")
|
||||
}
|
||||
}
|
||||
)
|
||||
group.leave()
|
||||
}
|
||||
} else {
|
||||
group.leave()
|
||||
}
|
||||
}
|
||||
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
// 所有图片加载完成后的处理
|
||||
group.notify(queue: .main) {
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
// Sort the images by their original index to maintain selection order
|
||||
let sortedImages = loadedImages.sorted { $0.key < $1.key }.map { $0.value }
|
||||
self.parent.selectedImages.append(contentsOf: sortedImages)
|
||||
|
||||
// Dismiss the picker
|
||||
=======
|
||||
let sortedImages = loadedImages.sorted { $0.key < $1.key }.map { $0.value }
|
||||
self.parent.selectedImages.append(contentsOf: sortedImages)
|
||||
>>>>>>> a4890a4 (feat: 图片上传互获取url)
|
||||
=======
|
||||
// 按原始顺序排序并更新图片数组
|
||||
let sortedImages = loadedImages.sorted { $0.key < $1.key }.map { $0.value }
|
||||
self.parent.selectedImages.append(contentsOf: sortedImages)
|
||||
|
||||
// 关闭图片选择器
|
||||
>>>>>>> a207b78 (feat: 确认上传)
|
||||
=======
|
||||
// 所有上传任务完成后的处理
|
||||
=======
|
||||
>>>>>>> 8e641fd (feat: 上传进度)
|
||||
group.notify(queue: .main) { [weak self] in
|
||||
guard let self = self else { return }
|
||||
|
||||
if let error = lastError {
|
||||
self.parent.onImageUploaded?(.failure(error))
|
||||
} else {
|
||||
let sortedImages = loadedImages.sorted { $0.key < $1.key }.map { $0.value }
|
||||
self.parent.selectedImages.append(contentsOf: sortedImages)
|
||||
|
||||
if let firstResult = uploadResults.first?.value {
|
||||
self.parent.onImageUploaded?(.success(firstResult))
|
||||
} else {
|
||||
self.parent.onImageUploaded?(.failure(NSError(
|
||||
domain: "com.wake.upload",
|
||||
code: -1,
|
||||
userInfo: [NSLocalizedDescriptionKey: "上传过程中出现错误"]
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
// 5. 关闭图片选择器
|
||||
>>>>>>> 5611df8 (feat: 素材上传成)
|
||||
=======
|
||||
>>>>>>> 8e641fd (feat: 上传进度)
|
||||
picker.dismiss(animated: true)
|
||||
=======
|
||||
self.parent.presentationMode.wrappedValue.dismiss()
|
||||
>>>>>>> 5edee64 (feat: 文件上传成功)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
// MARK: - Avatar Uploader Component
|
||||
=======
|
||||
// MARK: - AvatarUploader
|
||||
|
||||
/// 头像上传视图,提供头像选择功能
|
||||
/// 封装了头像显示和选择逻辑,支持点击选择新头像
|
||||
>>>>>>> a207b78 (feat: 确认上传)
|
||||
=======
|
||||
// MARK: - Avatar Uploader
|
||||
|
||||
/// 头像上传视图,提供头像选择功能
|
||||
>>>>>>> 8e641fd (feat: 上传进度)
|
||||
struct AvatarUploader: View {
|
||||
@Binding var selectedImage: UIImage?
|
||||
let size: CGFloat
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
var onUploadComplete: ((Result<ImageUploadService.UploadResults, Error>) -> Void)?
|
||||
|
||||
/// 上传完成回调,返回上传结果或错误
|
||||
=======
|
||||
>>>>>>> 8e641fd (feat: 上传进度)
|
||||
var onUploadComplete: ((Result<UploadResults, Error>) -> Void)?
|
||||
=======
|
||||
var onUploadComplete: ((Result<ImageUploadService.UploadResults, Error>) -> Void)?
|
||||
>>>>>>> 5edee64 (feat: 文件上传成功)
|
||||
|
||||
@State private var isImagePickerPresented = false
|
||||
|
||||
var body: some View {
|
||||
Button(action: { isImagePickerPresented = true }) {
|
||||
Button(action: {
|
||||
isImagePickerPresented = true
|
||||
}) {
|
||||
ZStack {
|
||||
<<<<<<< HEAD
|
||||
// Avatar Image or Placeholder
|
||||
=======
|
||||
>>>>>>> a4890a4 (feat: 图片上传互获取url)
|
||||
if let selectedImage = selectedImage {
|
||||
Image(uiImage: selectedImage)
|
||||
.resizable()
|
||||
@ -670,17 +89,7 @@ struct AvatarUploader: View {
|
||||
.frame(width: size, height: size)
|
||||
.clipShape(RoundedRectangle(cornerRadius: size * 0.1))
|
||||
} else {
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
// Default avatar container
|
||||
=======
|
||||
>>>>>>> a4890a4 (feat: 图片上传互获取url)
|
||||
=======
|
||||
// 默认头像占位视图
|
||||
>>>>>>> a207b78 (feat: 确认上传)
|
||||
=======
|
||||
>>>>>>> 8e641fd (feat: 上传进度)
|
||||
Color.gray.opacity(0.1)
|
||||
.frame(width: size, height: size)
|
||||
.overlay(
|
||||
@ -695,27 +104,9 @@ struct AvatarUploader: View {
|
||||
}
|
||||
}
|
||||
.frame(width: size, height: size)
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
.contentShape(Rectangle()) // Make the entire area tappable
|
||||
}
|
||||
.buttonStyle(PlainButtonStyle()) // Remove button highlight effect
|
||||
=======
|
||||
.contentShape(Rectangle())
|
||||
}
|
||||
.buttonStyle(PlainButtonStyle())
|
||||
>>>>>>> a4890a4 (feat: 图片上传互获取url)
|
||||
=======
|
||||
.contentShape(Rectangle()) // 确保整个区域都可点击
|
||||
}
|
||||
.buttonStyle(PlainButtonStyle()) // 使用无样式按钮
|
||||
>>>>>>> a207b78 (feat: 确认上传)
|
||||
=======
|
||||
.contentShape(Rectangle())
|
||||
}
|
||||
.buttonStyle(PlainButtonStyle())
|
||||
>>>>>>> 8e641fd (feat: 上传进度)
|
||||
.sheet(isPresented: $isImagePickerPresented) {
|
||||
PhotoPicker(
|
||||
selectedImages: Binding(
|
||||
@ -724,13 +115,7 @@ struct AvatarUploader: View {
|
||||
selectedImage = images.first
|
||||
}
|
||||
),
|
||||
selectionLimit: 1,
|
||||
onImageUploaded: { result in
|
||||
onUploadComplete?(result)
|
||||
},
|
||||
onUploadProgress: { progress in
|
||||
print("上传进度:\(progress.current)/\(progress.total),进度:\(Int(progress.progress * 100))%")
|
||||
}
|
||||
selectionLimit: 1
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,15 +7,7 @@ public class ImageUploaderGetID: ObservableObject {
|
||||
// MARK: - 类型定义
|
||||
|
||||
/// 上传结果
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
public struct UploadResult: Codable {
|
||||
=======
|
||||
public struct UploadResult {
|
||||
>>>>>>> a207b78 (feat: 确认上传)
|
||||
=======
|
||||
public struct UploadResult: Codable {
|
||||
>>>>>>> 5edee64 (feat: 文件上传成功)
|
||||
public let fileUrl: String
|
||||
public let fileName: String
|
||||
public let fileSize: Int
|
||||
@ -37,14 +29,7 @@ public class ImageUploaderGetID: ObservableObject {
|
||||
case invalidResponse
|
||||
case uploadFailed(Error?)
|
||||
case invalidFileId
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
case invalidResponseData
|
||||
=======
|
||||
>>>>>>> a207b78 (feat: 确认上传)
|
||||
=======
|
||||
case invalidResponseData
|
||||
>>>>>>> 5edee64 (feat: 文件上传成功)
|
||||
|
||||
public var errorDescription: String? {
|
||||
switch self {
|
||||
@ -60,16 +45,8 @@ public class ImageUploaderGetID: ObservableObject {
|
||||
return "上传失败: \(error?.localizedDescription ?? "未知错误")"
|
||||
case .invalidFileId:
|
||||
return "无效的文件ID"
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
case .invalidResponseData:
|
||||
return "无效的响应数据"
|
||||
=======
|
||||
>>>>>>> a207b78 (feat: 确认上传)
|
||||
=======
|
||||
case .invalidResponseData:
|
||||
return "无效的响应数据"
|
||||
>>>>>>> 5edee64 (feat: 文件上传成功)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -95,10 +72,6 @@ public class ImageUploaderGetID: ObservableObject {
|
||||
/// 上传图片到服务器
|
||||
/// - Parameters:
|
||||
/// - image: 要上传的图片
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
>>>>>>> 8e641fd (feat: 上传进度)
|
||||
/// - progress: 上传进度回调 (0.0 到 1.0)
|
||||
/// - completion: 完成回调
|
||||
public func uploadImage(
|
||||
@ -106,13 +79,6 @@ public class ImageUploaderGetID: ObservableObject {
|
||||
progress: @escaping (Double) -> Void,
|
||||
completion: @escaping (Result<UploadResult, Error>) -> Void
|
||||
) {
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
/// - completion: 完成回调,返回Result类型的结果
|
||||
public func uploadImage(_ image: UIImage, completion: @escaping (Result<UploadResult, Error>) -> Void) {
|
||||
>>>>>>> a207b78 (feat: 确认上传)
|
||||
=======
|
||||
>>>>>>> 8e641fd (feat: 上传进度)
|
||||
print("🔄 开始准备上传图片...")
|
||||
|
||||
// 1. 转换图片为Data
|
||||
@ -127,10 +93,6 @@ public class ImageUploaderGetID: ObservableObject {
|
||||
getUploadURL(for: imageData) { [weak self] result in
|
||||
switch result {
|
||||
case .success((let fileId, let uploadURL)):
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
>>>>>>> 8e641fd (feat: 上传进度)
|
||||
print("📤 获取到上传URL,开始上传文件...")
|
||||
|
||||
// 3. 上传文件
|
||||
@ -159,21 +121,8 @@ public class ImageUploaderGetID: ObservableObject {
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
<<<<<<< HEAD
|
||||
case .failure(let error):
|
||||
print("❌ 获取上传URL失败: \(error.localizedDescription)")
|
||||
=======
|
||||
// 3. 确认上传
|
||||
self?.confirmUpload(fileId: fileId, fileName: "avatar_\(UUID().uuidString).jpg", fileSize: imageData.count) { confirmResult in
|
||||
completion(confirmResult)
|
||||
}
|
||||
case .failure(let error):
|
||||
>>>>>>> a207b78 (feat: 确认上传)
|
||||
=======
|
||||
case .failure(let error):
|
||||
print("❌ 获取上传URL失败: \(error.localizedDescription)")
|
||||
>>>>>>> 8e641fd (feat: 上传进度)
|
||||
completion(.failure(error))
|
||||
}
|
||||
}
|
||||
@ -214,7 +163,11 @@ public class ImageUploaderGetID: ObservableObject {
|
||||
}
|
||||
|
||||
// 2. 获取上传URL
|
||||
getUploadURL(for: videoData, mimeType: mimeType, originalFilename: videoURL.lastPathComponent) { [weak self] result in
|
||||
getUploadURL(
|
||||
for: videoData,
|
||||
mimeType: mimeType,
|
||||
originalFilename: videoURL.lastPathComponent
|
||||
) { [weak self] result in
|
||||
switch result {
|
||||
case .success((let fileId, let uploadURL)):
|
||||
print("📤 获取到视频上传URL,开始上传文件...")
|
||||
@ -254,7 +207,10 @@ public class ImageUploaderGetID: ObservableObject {
|
||||
// MARK: - 私有方法
|
||||
|
||||
/// 获取上传URL
|
||||
private func getUploadURL(for imageData: Data, completion: @escaping (Result<(fileId: String, uploadURL: URL), Error>) -> Void) {
|
||||
private func getUploadURL(
|
||||
for imageData: Data,
|
||||
completion: @escaping (Result<(fileId: String, uploadURL: URL), Error>) -> Void
|
||||
) {
|
||||
let fileName = "avatar_\(UUID().uuidString).jpg"
|
||||
let parameters: [String: Any] = [
|
||||
"filename": fileName,
|
||||
@ -321,11 +277,6 @@ public class ImageUploaderGetID: ObservableObject {
|
||||
}
|
||||
|
||||
/// 获取上传URL
|
||||
/// - Parameters:
|
||||
/// - fileData: 要上传的文件数据
|
||||
/// - mimeType: 文件MIME类型
|
||||
/// - originalFilename: 原始文件名
|
||||
/// - completion: 完成回调
|
||||
private func getUploadURL(
|
||||
for fileData: Data,
|
||||
mimeType: String,
|
||||
@ -399,19 +350,14 @@ public class ImageUploaderGetID: ObservableObject {
|
||||
}
|
||||
|
||||
/// 确认上传
|
||||
private func confirmUpload(fileId: String, fileName: String, fileSize: Int, completion: @escaping (Result<UploadResult, Error>) -> Void) {
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
private func confirmUpload(
|
||||
fileId: String,
|
||||
fileName: String,
|
||||
fileSize: Int,
|
||||
completion: @escaping (Result<UploadResult, Error>) -> Void
|
||||
) {
|
||||
let endpoint = "\(apiConfig.baseURL)/file/confirm-upload"
|
||||
guard let url = URL(string: endpoint) else {
|
||||
=======
|
||||
let urlString = "\(apiConfig.baseURL)/file/confirm-upload"
|
||||
guard let url = URL(string: urlString) else {
|
||||
>>>>>>> a207b78 (feat: 确认上传)
|
||||
=======
|
||||
let endpoint = "\(apiConfig.baseURL)/file/confirm-upload"
|
||||
guard let url = URL(string: endpoint) else {
|
||||
>>>>>>> 5edee64 (feat: 文件上传成功)
|
||||
completion(.failure(UploadError.invalidURL))
|
||||
return
|
||||
}
|
||||
@ -420,58 +366,28 @@ public class ImageUploaderGetID: ObservableObject {
|
||||
request.httpMethod = "POST"
|
||||
request.allHTTPHeaderFields = apiConfig.authHeaders
|
||||
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
>>>>>>> 5edee64 (feat: 文件上传成功)
|
||||
let body: [String: Any] = [
|
||||
"file_id": fileId,
|
||||
"file_name": fileName,
|
||||
"file_size": fileSize
|
||||
]
|
||||
<<<<<<< HEAD
|
||||
|
||||
do {
|
||||
request.httpBody = try JSONSerialization.data(withJSONObject: body)
|
||||
print("📤 确认上传请求,fileId: \(fileId), 文件名: \(fileName)")
|
||||
} catch {
|
||||
print("❌ 序列化确认上传参数失败: \(error.localizedDescription)")
|
||||
=======
|
||||
let requestBody: [String: Any] = ["file_id": fileId]
|
||||
=======
|
||||
>>>>>>> 5edee64 (feat: 文件上传成功)
|
||||
|
||||
do {
|
||||
request.httpBody = try JSONSerialization.data(withJSONObject: body)
|
||||
print("📤 确认上传请求,fileId: \(fileId), 文件名: \(fileName)")
|
||||
} catch {
|
||||
<<<<<<< HEAD
|
||||
>>>>>>> a207b78 (feat: 确认上传)
|
||||
=======
|
||||
print("❌ 序列化确认上传参数失败: \(error.localizedDescription)")
|
||||
>>>>>>> 5edee64 (feat: 文件上传成功)
|
||||
completion(.failure(error))
|
||||
return
|
||||
}
|
||||
|
||||
let task = session.dataTask(with: request) { data, response, error in
|
||||
if let error = error {
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
print("❌ 确认上传请求失败: \(error.localizedDescription)")
|
||||
=======
|
||||
>>>>>>> a207b78 (feat: 确认上传)
|
||||
=======
|
||||
print("❌ 确认上传请求失败: \(error.localizedDescription)")
|
||||
>>>>>>> 5edee64 (feat: 文件上传成功)
|
||||
completion(.failure(UploadError.uploadFailed(error)))
|
||||
return
|
||||
}
|
||||
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
>>>>>>> 5edee64 (feat: 文件上传成功)
|
||||
guard let httpResponse = response as? HTTPURLResponse else {
|
||||
print("❌ 无效的服务器响应")
|
||||
completion(.failure(UploadError.invalidResponse))
|
||||
@ -483,14 +399,6 @@ public class ImageUploaderGetID: ObservableObject {
|
||||
let errorMessage = "确认上传失败,状态码: \(statusCode)"
|
||||
print("❌ \(errorMessage)")
|
||||
completion(.failure(UploadError.serverError(errorMessage)))
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
guard let httpResponse = response as? HTTPURLResponse,
|
||||
(200...299).contains(httpResponse.statusCode) else {
|
||||
completion(.failure(UploadError.serverError("确认上传失败,状态码: \((response as? HTTPURLResponse)?.statusCode ?? -1)")))
|
||||
>>>>>>> a207b78 (feat: 确认上传)
|
||||
=======
|
||||
>>>>>>> 5edee64 (feat: 文件上传成功)
|
||||
return
|
||||
}
|
||||
|
||||
@ -508,18 +416,8 @@ public class ImageUploaderGetID: ObservableObject {
|
||||
|
||||
task.resume()
|
||||
}
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
>>>>>>> 8e641fd (feat: 上传进度)
|
||||
|
||||
/// 上传文件到指定URL
|
||||
/// - Parameters:
|
||||
/// - fileData: 要上传的文件数据
|
||||
/// - uploadURL: 上传URL
|
||||
/// - mimeType: 文件MIME类型
|
||||
/// - onProgress: 进度回调,0.0 到 1.0
|
||||
/// - completion: 完成回调
|
||||
public func uploadFile(
|
||||
fileData: Data,
|
||||
to uploadURL: URL,
|
||||
@ -531,34 +429,19 @@ public class ImageUploaderGetID: ObservableObject {
|
||||
request.httpMethod = "PUT"
|
||||
request.setValue(mimeType, forHTTPHeaderField: "Content-Type")
|
||||
|
||||
let task = session.uploadTask(
|
||||
with: request,
|
||||
from: fileData
|
||||
) { _, response, error in
|
||||
let task = session.uploadTask(with: request, from: fileData) { _, response, error in
|
||||
if let error = error {
|
||||
completion(.failure(error))
|
||||
return
|
||||
}
|
||||
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
>>>>>>> 5edee64 (feat: 文件上传成功)
|
||||
guard let httpResponse = response as? HTTPURLResponse else {
|
||||
completion(.failure(UploadError.invalidResponse))
|
||||
return
|
||||
}
|
||||
|
||||
guard httpResponse.statusCode >= 200 && httpResponse.statusCode < 300 else {
|
||||
guard (200...299).contains(httpResponse.statusCode) else {
|
||||
let statusCode = httpResponse.statusCode
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
guard let httpResponse = response as? HTTPURLResponse,
|
||||
(200...299).contains(httpResponse.statusCode) else {
|
||||
let statusCode = (response as? HTTPURLResponse)?.statusCode ?? -1
|
||||
>>>>>>> 8e641fd (feat: 上传进度)
|
||||
=======
|
||||
>>>>>>> 5edee64 (feat: 文件上传成功)
|
||||
completion(.failure(UploadError.serverError("上传失败,状态码: \(statusCode)")))
|
||||
return
|
||||
}
|
||||
@ -568,7 +451,7 @@ public class ImageUploaderGetID: ObservableObject {
|
||||
|
||||
// 添加进度观察
|
||||
if #available(iOS 11.0, *) {
|
||||
let progressObserver = task.progress.observe(\.fractionCompleted) { (progressValue, _) in
|
||||
let progressObserver = task.progress.observe(\.fractionCompleted) { progressValue, _ in
|
||||
DispatchQueue.main.async {
|
||||
onProgress(progressValue.fractionCompleted)
|
||||
}
|
||||
@ -579,15 +462,6 @@ public class ImageUploaderGetID: ObservableObject {
|
||||
task?.progress.cancel()
|
||||
}
|
||||
} else {
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
// iOS 11 以下版本使用通知
|
||||
=======
|
||||
// Fallback for earlier iOS versions
|
||||
>>>>>>> 8e641fd (feat: 上传进度)
|
||||
=======
|
||||
// iOS 11 以下版本使用通知
|
||||
>>>>>>> 5edee64 (feat: 文件上传成功)
|
||||
var lastProgress: Double = 0
|
||||
let timer = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { timer in
|
||||
let bytesSent = task.countOfBytesSent
|
||||
@ -655,7 +529,12 @@ private class TaskObserver: NSObject {
|
||||
handlers.append(handler)
|
||||
}
|
||||
|
||||
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
|
||||
override func observeValue(
|
||||
forKeyPath keyPath: String?,
|
||||
of object: Any?,
|
||||
change: [NSKeyValueChangeKey: Any]?,
|
||||
context: UnsafeMutableRawPointer?
|
||||
) {
|
||||
guard keyPath == #keyPath(URLSessionTask.state),
|
||||
let task = task,
|
||||
task.state == .completed else {
|
||||
@ -712,11 +591,6 @@ private extension URLSessionTask {
|
||||
}
|
||||
}
|
||||
}
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
>>>>>>> a207b78 (feat: 确认上传)
|
||||
=======
|
||||
>>>>>>> 8e641fd (feat: 上传进度)
|
||||
}
|
||||
|
||||
// MARK: - 响应模型
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user