XuqmGroup-iOSSDK/Sources/XuqmSDK/File/FileSDK.swift
XuqmGroup 44bb4c2ebe feat(im): 添加即时消息SDK核心功能实现
- 实现了聊天消息发送功能,支持文本、图片、视频、音频、文件等多种消息类型
- 集成了文件上传下载功能,支持多媒体文件的传输和管理
- 添加了群组管理功能,包括创建群组、成员管理、权限控制等操作
- 实现了好友系统,支持好友添加、删除、分组等功能
- 集成了黑名单管理,提供用户屏蔽和解除屏蔽功能
- 添加了会话管理功能,支持对话列表、未读消息统计等
- 实现了历史消息查询和搜索功能
- 添加了实时连接状态管理和自动重连机制
2026-05-03 00:11:06 +08:00

86 行
3.2 KiB
Swift

import Foundation
import UniformTypeIdentifiers
public struct FileUploadResult: Codable, Sendable {
public let url: String
public let thumbnailUrl: String?
public let hash: String
public let size: Int64
public let originalName: String?
public let mimeType: String?
public let ext: String?
}
public final class FileSDK: @unchecked Sendable {
public static let shared = FileSDK()
private init() {}
public func upload(fileURL: URL, thumbnailData: Data? = nil) async throws -> FileUploadResult {
let config = await XuqmSDK.shared.requireConfig()
let tokenStore = await XuqmSDK.shared.tokenStore
let boundary = "Boundary-\(UUID().uuidString)"
let url = SDKEndpoints.apiBaseURL.appendingPathComponent("api/file/upload")
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
if let token = tokenStore?.get() {
request.setValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
}
let body = try createMultipartBody(fileURL: fileURL, boundary: boundary, thumbnailData: thumbnailData)
let (data, response) = try await URLSession.shared.upload(for: request, from: body)
guard let http = response as? HTTPURLResponse, (200..<300).contains(http.statusCode) else {
throw URLError(.badServerResponse)
}
let wrapper = try JSONDecoder().decode(ApiResponse<FileUploadResult>.self, from: data)
guard let result = wrapper.data else {
throw URLError(.cannotDecodeContentData)
}
return result
}
private func createMultipartBody(fileURL: URL, boundary: String, thumbnailData: Data?) throws -> Data {
var body = Data()
let filename = fileURL.lastPathComponent
let mimeType: String
if #available(iOS 14.0, macOS 11.0, *) {
if let uti = UTType(filenameExtension: (fileURL.path as NSString).pathExtension),
let preferred = uti.preferredMIMEType {
mimeType = preferred
} else {
mimeType = "application/octet-stream"
}
} else {
mimeType = "application/octet-stream"
}
body.append("--\(boundary)\r\n")
body.append("Content-Disposition: form-data; name=\"file\"; filename=\"\(filename)\"\r\n")
body.append("Content-Type: \(mimeType)\r\n\r\n")
body.append(try Data(contentsOf: fileURL))
body.append("\r\n")
if let thumbnailData {
let thumbFilename = "\((filename as NSString).deletingPathExtension)_thumb.jpg"
body.append("--\(boundary)\r\n")
body.append("Content-Disposition: form-data; name=\"thumbnail\"; filename=\"\(thumbFilename)\"\r\n")
body.append("Content-Type: image/jpeg\r\n\r\n")
body.append(thumbnailData)
body.append("\r\n")
}
body.append("--\(boundary)--\r\n")
return body
}
}
private extension Data {
mutating func append(_ string: String) {
if let data = string.data(using: .utf8) {
append(data)
}
}
}