在将zipe文件(1.6gb)转换为字节后,我试图将zip文件上传到Nexus存储库。问题是当它读取zip文件的字节时,如果文件大小很大,就会抛出system.outofmemory错误。如果它只有3-600mb,它不会抛出错误,有办法读取字节并避免oufofmemory错误吗?
使用"1“参数调用"ReadAllText”的异常:“类型为'System.OutOfMemoryException‘的异常被抛出。”
$fileBin = System.IO.File::ReadAlltext($File)
Function Upload-File-To-Nexus {
[CmdletBinding()]
Param(
[Parameter(Mandatory = $True )][ValidateNotNullOrEmpty()][string]$File, # aka File
[parameter(Mandatory = $True )][ValidateNotNullOrEmpty()][string]$Repository,
[parameter(Mandatory = $True )][ValidateNotNullOrEmpty()][string]$Directory,
[Parameter(Mandatory = $False)][ValidateNotNullOrEmpty()][string]$FileName # destination filename, which can be derived from uploaded file
)
Begin {
$token = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes("fahq-ra-build:tEDlCI=0m9CES8l*lk?b"))
$header = @{authorization = "Basic $token" }
$Uri = "https://nexus-arps.corp.firstam.com/service/rest/v1/components?repository=${Repository}"
$boundary = [System.Guid]::NewGuid().ToString()
$LF = "`r`n"
}
Process {
If (!($FileName -ne $Null -And $FileName -ne "")) {
# if filename is null, then just use the filename from the input file
$FileName = Split-Path $File -Leaf
}
Try { $fileBin = [System.IO.File]::ReadAlltext($File) }
Catch {
throw $_.exception
Throw "Unable to read file $File. Aborted."
}
$bodyLines = (
"--${boundary}",
"Content-Disposition: form-data; name=`"raw.directory`"",
"",
"${Directory}",
"--${boundary}",
"Content-Disposition: form-data; name=`"raw.asset1`"; filename=`"${FileName}`"",
"Content-Type: application/octet-stream",
"",
$file,
"",
"--${boundary}",
"Content-Disposition: form-data; name=`"raw.asset1.filename`"",
"",
"${FileName}",
"--${boundary}--",
""
) -join $LF
$Response = Invoke-WebRequest -Uri $Uri -Method "POST" -Headers $header -ContentType "multipart/form-data; boundary=`"$boundary`"" -Body $bodyLines
If ($Response.StatusCode -ge 200 -And $Response.StatusCode -lt 300) {
$Output = "https://${Server}/repository/${repository}/${directory}/${FileName}" -Replace "//", "/"
Write-Output $Output
}
Else {
Write-Output $Response
}
}
}发布于 2020-12-15 22:32:06
考虑到您没有处理基于文本的文件,您可能是指.ReadAllBytes()。
但是,您不必将该文件加载到内存中--使用Invoke-WebRequest的-InFile参数来指定要上载的文件。
发布于 2020-12-15 22:34:01
IIRC,ReadAllBytes()的工作方式是它不知道或不预先查找文件大小。相反,它猜测产生的字节数组的缓冲区大小。当猜测失败时,它会加倍猜测,分配一个新数组,并复制到目前为止读取的内容。这会重复执行,直到加载文件为止。
那么,您不仅可以从实际耗尽内存中获得OutOfMemory,而且还可以从额外的缓冲区中运行当前进程中的地址空间,在该缓冲区中,默认情况下,单个进程仅限于2GB。
如果这听起来很糟糕,而且效率很低,那么您是对的,而且RealAllBytes()实际上只对小文件有用。
在处理较大的文件时,您需要使用流API,例如File.OpenRead()。在这里,您可以检查文件的实际大小,使用它分配确切的字节数组,然后一次读取一个小块(例如,4K)。
更好的是,由于您已经在使用Invoke-WebRequest,您知道它是supports a -InFile argument吗?它可以用于上传文件而不将整个文件加载到内存中?
https://stackoverflow.com/questions/65314577
复制相似问题