-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathAdd-GoogleDriveFile.ps1
More file actions
192 lines (156 loc) · 5.45 KB
/
Add-GoogleDriveFile.ps1
File metadata and controls
192 lines (156 loc) · 5.45 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
<#
.SYNOPSIS
Uploads a file to Google Drive in a specified folder.
.DESCRIPTION
Uploads a file to Google Drive, places it in the "Open Live Writer" subfolder,
preserves the original filename.
.PARAMETER FilePath
The local path to the file to upload.
.PARAMETER FileName
Optional custom name for the file. If not specified, uses the original filename.
.PARAMETER Force
If specified, will overwrite an existing file with the same name in the target folder.
If not specified and the file already exists, it will return the existing file's metadata.
.EXAMPLE
Add-GoogleDriveFile -FilePath "C:\images\photo.jpg"
#>
function Add-GoogleDriveFile {
[CmdletBinding()]
param(
[Parameter(Mandatory = $true)]
[ValidateScript({ Test-Path -Path $_ -PathType Leaf })]
[string]$FilePath,
[Parameter()]
[string]$FileName,
[Parameter()]
[string]$TargetFolderName = "PSBlogger",
[Parameter()]
[switch]$Force
)
$sourceItem = Get-Item (Resolve-Path $FilePath)
Write-Verbose "Add-GoogleDriveFile: Uploading file: $($sourceItem.FullName) to Google Drive"
if (-not $FileName) {
$FileName = $sourceItem.Name
}
# First, find or create the upload folder in Google Drive
Write-Verbose "Add-GoogleDriveFile: Verifying target folder: $TargetFolderName"
$folder = Get-GoogleDriveItems -ResultType "Folders" -Title $TargetFolderName
if (-not $folder) {
# Create the folder if it doesn't exist
Write-Verbose "Add-GoogleDriveFile: Folder '$TargetFolderName' not found. Creating new folder."
$folder = Add-GoogleDriveFolder -Name $TargetFolderName
}
else {
# Get the first folder if multiple exist
Write-Verbose "Add-GoogleDriveFile: Folder '$TargetFolderName' found."
$folder = $folder | Select-Object -First 1
}
# Determine if the file already exists in the target folder
Write-Verbose "Add-GoogleDriveFile: Checking if file '$FileName' already exists in folder '$TargetFolderName'"
$existingFile = Get-GoogleDriveItems -ResultType "Files" -Title $FileName -ParentId $folder.id
if ($existingFile) {
if (-not $Force) {
# use existing file
return New-GoogleDriveMetadata -id $existingFile.id -name $existingFile.name
}
# address multiple file issue
# todo: evaluate additional meta-data of the file to ensure it's not deleted
$existingFile = $existingFile | Select-Object -First 1
}
$sourceMime = Get-ImageMimeType -Extension $sourceItem.Extension
# Prepare metadata for the file
$metadata = @{
name = $FileName
parents = @($folder.id)
} | ConvertTo-Json -Compress
$fileContent = [System.IO.File]::ReadAllBytes($sourceItem.FullName)
$fileContentBase64 = [Convert]::ToBase64String($fileContent)
# Create multipart body
$boundary = "boundary_" + [System.Guid]::NewGuid().ToString()
$body = @(
# Metadata part
"--$boundary"
"Content-Type: application/json; charset=UTF-8"
""
$metadata
"--$boundary"
# File content part
"Content-Type: $sourceMime"
"Content-Transfer-Encoding: base64"
""
$fileContentBase64
"--$boundary--"
) -join "`r`n"
$additionalHeaders = @{
"Content-Type" = "multipart/related; boundary=$boundary"
}
try {
if ($existingFile) {
# If the file exists and Force is specified, update it
$uri = "https://www.googleapis.com/upload/drive/v3/files/$($existingFile.id)?uploadType=media"
$method = "PATCH"
"Add-GoogleDriveFile: $Method $uri" | Write-Verbose
$uploadResult = Invoke-GApi -uri $uri -InFile $sourceItem.FullName -method $method -ContentType $sourceMime -Verbose:$false
}
else {
$uri = "https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart"
$method = "POST"
"Add-GoogleDriveFile: $Method $uri" | Write-Verbose
$uploadResult = Invoke-GApi -uri $uri -body $body -method $method -ContentType "multipart/related; boundary=$boundary" -AdditionalHeaders $additionalHeaders -Verbose:$false
}
# Return the file information with public URL
return New-GoogleDriveMetadata -id $uploadResult.id -name $uploadResult.name
}
catch {
Write-Error "Failed to upload file to Google Drive: $($_.Exception.Message). $($_.ErrorDetails | ConvertTo-Json -Depth 10)" -ErrorAction Stop
}
}
<#
.SYNOPSIS
Gets the MIME type for common image file extensions.
.DESCRIPTION
Returns the appropriate MIME type for image files. Falls back to application/octet-stream for unknown types.
.PARAMETER Extension
The file extension (including the dot).
.EXAMPLE
Get-ImageMimeType -Extension ".jpg"
#>
function Get-ImageMimeType {
[CmdletBinding()]
param(
[Parameter(Mandatory = $true)]
[string]$Extension
)
$mimeTypes = @{
'.jpg' = 'image/jpeg'
'.jpeg' = 'image/jpeg'
'.png' = 'image/png'
'.gif' = 'image/gif'
'.bmp' = 'image/bmp'
'.webp' = 'image/webp'
'.svg' = 'image/svg+xml'
'.ico' = 'image/x-icon'
'.tiff' = 'image/tiff'
'.tif' = 'image/tiff'
}
$normalizedExtension = $Extension.ToLower()
if ($mimeTypes.ContainsKey($normalizedExtension)) {
return $mimeTypes[$normalizedExtension]
}
else {
return 'application/octet-stream'
}
}
function New-GoogleDriveMetadata {
param(
[string]$id,
[string]$name
)
$publicUrl = "https://lh3.googleusercontent.com/d/$id"
return [PSCustomObject]@{
Id = $id
Name = $name
PublicUrl = $publicUrl
DriveUrl = "https://drive.google.com/file/d/$id/view"
}
}