| 42 | } |
| 43 | |
| 44 | export class GoogleDriveFileWriter implements FileWriter { |
| 45 | path: string; |
| 46 | |
| 47 | fs: GoogleDriveFileSystem; |
| 48 | |
| 49 | constructor(fs: GoogleDriveFileSystem, path: string) { |
| 50 | this.fs = fs; |
| 51 | this.path = path; |
| 52 | } |
| 53 | |
| 54 | async write(content: string | Blob): Promise<void> { |
| 55 | try { |
| 56 | return await this.writeWithResolvedParent(content); |
| 57 | } catch (error) { |
| 58 | if (!isNotFoundError(error)) { |
| 59 | throw error; |
| 60 | } |
| 61 | this.fs.clearPathCache(); |
| 62 | return await this.writeWithResolvedParent(content); |
| 63 | } |
| 64 | } |
| 65 | |
| 66 | private async writeWithResolvedParent(content: string | Blob): Promise<void> { |
| 67 | // 解析文件路径和文件名 |
| 68 | const pathParts = this.path.split("/").filter(Boolean); |
| 69 | const fileName = pathParts.pop() || ""; // 获取文件名 |
| 70 | const dirPath = "/" + pathParts.join("/"); // 重建目录路径 |
| 71 | |
| 72 | // 使用优化的方法确保目录存在并获取ID |
| 73 | const parentId = await this.fs.ensureDirExists(dirPath); |
| 74 | |
| 75 | // 使用优化的查找方法 |
| 76 | const existingFileId = await this.fs.findFileInDirectory(fileName, parentId); |
| 77 | |
| 78 | if (existingFileId) { |
| 79 | // 如果文件存在,则更新 |
| 80 | return this.updateFile(existingFileId, content); |
| 81 | } else { |
| 82 | // 如果文件不存在,则创建 |
| 83 | return this.createNewFile(fileName, parentId, content); |
| 84 | } |
| 85 | } |
| 86 | |
| 87 | private async updateFile(fileId: string, content: string | Blob): Promise<void> { |
| 88 | // 不设置Content-Type,让浏览器自动处理multipart/form-data边界 |
| 89 | |
| 90 | const metadata = { |
| 91 | // 只更新内容,不更新元数据 |
| 92 | }; |
| 93 | |
| 94 | const formData = new FormData(); |
| 95 | formData.append("metadata", new Blob([JSON.stringify(metadata)], { type: "application/json" })); |
| 96 | formData.append("file", content instanceof Blob ? content : new Blob([content])); |
| 97 | |
| 98 | await this.fs.request( |
| 99 | `https://www.googleapis.com/upload/drive/v3/files/${fileId}?uploadType=multipart&spaces=appDataFolder`, |
| 100 | { |
| 101 | method: "PATCH", |
nothing calls this directly
no outgoing calls
no test coverage detected