通过PowerShell上传文件至Wasabi S3时遇410及请求体终止错误
问题
使用PowerShell脚本将SharePoint文件下载后上传至Wasabi S3指定存储桶及文件夹,下载功能正常,但上传进度到100%后终止,报错The request body terminated unexpectedly。联系Wasabi支持后,对方反馈日志中存在410错误,且已拥有S3完全权限,当前使用的脚本如下:
$SiteUrl = "sharepoint site" $LibraryName = "Documents" $FolderName = "Archive" $S3BucketName = "Bucket" $S3Region = "eu-central-2" $AccessKey = "Access_Key" $SecretKey = "Secret_Key" $LocalTempFolder = "Folderpath" $WasabiEndpoint = "https://s3.eu-central-2.wasabisys.com" Import-Module PnP.PowerShell Import-Module AWSPowerShell.NetCore function Convert-HexStringToByteArray { param ( [string]$HexString ) if ($HexString.Length % 2 -ne 0) { throw "Hex string length must be even." } $ByteArray = for ($i = 0; $i -lt $HexString.Length; $i += 2) { [Convert]::ToByte($HexString.Substring($i, 2), 16) } return $ByteArray } function Upload-ToWasabi { param ( [string]$FilePath, [string]$S3Key, [int]$RetryCount = 3 ) for ($Attempt = 1; $Attempt -le $RetryCount; $Attempt++) { try { Write-Host "Uploading item to Wasabi S3: $S3Key (Attempt $Attempt of $RetryCount)" Write-S3Object -BucketName $S3BucketName ` -Key $S3Key ` -File $FilePath ` -Region $S3Region ` -ProfileName WasabiProfile ` -Endpoint $WasabiEndpoint ` -StorageClass STANDARD ` -PartSize 5MB ` -Verbose Write-Host "Upload successful for $S3Key." return $true } catch { Write-Host "Error during upload: $($_.Exception.Message)" Write-Host "Full error details: $($_.Exception)" if ($Attempt -lt $RetryCount) { Write-Host "Retrying upload in 5 seconds..." Start-Sleep -Seconds 5 } else { Write-Error "Failed to upload $S3Key after $RetryCount attempts." return $false } } } } Write-Host "Connecting to SharePoint..." Connect-PnPOnline -Url $SiteUrl -UseWebLogin if (-not (Test-Path -Path $LocalTempFolder)) { Write-Host "Creating temporary folder at $LocalTempFolder" New-Item -Path $LocalTempFolder -ItemType Directory } $SiteName = ($SiteUrl.Split('/'))[-1] Write-Host "Using SharePoint site name: $SiteName" try { Write-Host "Fetching the SharePoint library and folder..." $FolderRelativeUrl = "Shared Documents/$FolderName" Write-Host "Getting files from SharePoint folder: $FolderRelativeUrl" $Files = Get-PnPFolderItem -FolderSiteRelativeUrl $FolderRelativeUrl Write-Host "Items found in SharePoint folder: $($Files.Count)" foreach ($Item in $Files) { Write-Host "Processing item: $($Item.Name) - Type: $($Item.FileSystemObjectType)" $LocalFilePath = Join-Path -Path $LocalTempFolder -ChildPath $Item.Name try { Write-Host "Downloading item: $($Item.Name) to $LocalFilePath" Get-PnPFile -Url $Item.ServerRelativeUrl -Path $LocalTempFolder -FileName $Item.Name -AsFile -Force if (Test-Path $LocalFilePath) { $FileSize = (Get-Item $LocalFilePath).Length Write-Host "Item downloaded successfully: $LocalFilePath" Write-Host "Item size: $FileSize bytes" $S3Key = "$SiteName/$FolderName/$($Item.Name)" $UploadSuccess = Upload-ToWasabi -FilePath $LocalFilePath -S3Key $S3Key if (-not $UploadSuccess) { Write-Error "Failed to upload item to Wasabi: $S3Key" } } else { Write-Host "Error: Item was not downloaded properly: $LocalFilePath" } } catch { Write-Host "Error processing item: $($Item.Name)" Write-Error $_ } } } catch { Write-Error "An error occurred: $_" } finally { Write-Host "Disconnecting from SharePoint..." Disconnect-PnPOnline } Write-Host "Script completed successfully."
解决建议
- 修复凭证配置问题:脚本中指定了
-ProfileName WasabiProfile但未初始化该配置文件,添加凭证初始化步骤:
或者直接在# 在Import-Module后添加 Set-AWSCredential -AccessKey $AccessKey -SecretKey $SecretKey -StoreAs WasabiProfileWrite-S3Object中传入凭证,避免依赖本地配置:Write-S3Object -BucketName $S3BucketName ` -Key $S3Key ` -File $FilePath ` -Region $S3Region ` -Credential (New-Object Amazon.Runtime.BasicAWSCredentials($AccessKey, $SecretKey)) ` -Endpoint $WasabiEndpoint ` -StorageClass STANDARD ` -PartSize 10MB ` -ForcePathStyle ` -Verbose - 调整分片上传参数:将
-PartSize从5MB调整为10MB或更大,Wasabi对小分片的处理可能存在兼容性问题;同时添加-ForcePathStyle参数,强制使用路径样式访问,避免虚拟主机样式的潜在问题。 - 替换为AWS.Tools.S3模块:AWSPowerShell.NetCore是旧版模块,AWS.Tools.S3是官方推荐的模块化工具,对第三方S3兼容更好:
# 卸载旧模块(可选) Uninstall-Module AWSPowerShell.NetCore -Force # 安装新模块 Install-Module AWS.Tools.S3 -Force # 导入模块 Import-Module AWS.Tools.S3 - 验证文件完整性:上传前对比SharePoint文件大小与本地文件大小,确保下载过程中未出现文件损坏:
# 在Get-PnPFile后添加 $spFile = Get-PnPFile -Url $Item.ServerRelativeUrl -AsFile -Force -Path $LocalTempFolder -FileName $Item.Name $spFileSize = $spFile.Length $localFileSize = (Get-Item $LocalFilePath).Length if ($spFileSize -ne $localFileSize) { Write-Error "File size mismatch for $($Item.Name): SharePoint size $spFileSize, local size $localFileSize" continue } - 排查410错误原因:410表示目标资源不存在,确认存储桶是否存在、
$S3Key中的路径是否合法(避免特殊字符),可以手动在Wasabi控制台创建对应路径后再测试上传。
内容的提问来源于stack exchange,提问作者insil
相关产品推荐
相关产品推荐

