我的 Github 操作“发布”:
name: publish
on:
push:
tags:
- release-*
jobs:
test:
uses: ./.github/workflows/test.yml
secrets: inherit
publish:
name: Publish
needs: test
runs-on: windows-latest
strategy:
matrix:
dotnet-version: [ '8.0.x' ]
steps:
- uses: actions/checkout@v4
with:
submodules: true
token: ${{ secrets.CHECKOUT_TOKEN }}
- name: Instalar .NET SDK ${{ matrix.dotnet-version }}
uses: actions/setup-dotnet@v4
with:
dotnet-version: ${{ matrix.dotnet-version }}
- name: Agregar DevExpress Nuget source
run: dotnet nuget add source "https://nuget.devexpress.com/..../api"
- name: Ejecutar build.ps1
shell: pwsh
env:
DISABLE_PROGRESS: 1
NEXION_USERNAME: ${{ secrets.NEXION_USERNAME }}
NEXION_PASSWORD: ${{ secrets.NEXION_PASSWORD }}
run: .\build.ps1 -enableOutput
- uses: actions/upload-artifact@v4
with:
name: release-artifacts
path: .\build\**
步骤
.\build.ps1 -enableOutput
是一个脚本,它执行所有.exe生成,然后通过API将其输出上传到我自己的网站,如下所示:
function Get-MultipartBody($boundary, $paths, $fields) {
$boundary = "`r`n--" + $boundary
$multipart = @($fields.Keys + $paths) | % {
$name = if ($paths.IndexOf($_) -ne -1) {'upload_files'} else {$_}
$contentDisposition = "Content-Disposition: form-data; name=`"$name`""
$contentType = ''
$data = ''
if ($name -eq 'upload_files') {
$filename = [IO.Path]::GetFileName($_)
$contentDisposition = $contentDisposition + "; filename=`"$filename`""
$contentType = "`r`n`Content-Type: application/octet-stream"
$bytes = [IO.File]::ReadAllBytes($_)
$data = [Text.Encoding]::GetEncoding('ISO-8859-1').GetString($bytes)
} else {
$data = $fields.Item($_)
}
return $contentDisposition + $contentType + "`r`n`r`n" + $data
}
$middle = $multipart -join ($boundary + "`r`n")
return $boundary + "`r`n" + $middle + $boundary + "--"
}
...
$body = Get-MultipartBody $boundary $files $fields
...
Invoke-WebRequest -Uri "http://my-domain.com.ar/services/release/publish/add" -Method Post -Body $body -WebSession $session -ContentType "multipart/form-data; boundary=$boundary" -TimeoutSec 300000 -MaximumRedirection 0
...
我的问题是,不知何故,文件到达我的服务器 API,并被存储,但它们已损坏,而步骤
actions/upload-artifact@v4
在操作本身上很好地存储文件。
举个例子:
神器NexionSmartERP-AnyCPU-24.1.0.1.exe为82M(使用actions/upload-artifact@v4) 上传到我的服务器 API NexionSmartERP-AnyCPU-24.1.0.1.exe 的相同文件为 122M(几乎大了 50%,已损坏)
顺便说一句,.uild.ps1 脚本在我的主机上本地运行时可以正常发布到我的服务器 API。
我做错了什么?
解决方案是避免从二进制数据构建字符串,正如 @jdweng 指出的那样。
重构了我的 PowerShell 函数来构建临时文件,该文件支持文件上传和普通字段。
function Get-MultipartBody($boundary, $files, $fields) {
$tempFile = [System.IO.Path]::GetTempFileName()
$UTF8woBOM = New-Object "System.Text.UTF8Encoding" -ArgumentList @($false)
# Campos
if ($fields.Keys.Count -gt 0) {
$sw = New-Object System.IO.StreamWriter($tempFile, $true, $UTF8woBOM)
foreach($field in $fields.Keys) {
$sw.Write("`r`n--$boundary`r`nContent-Disposition: form-data; name=`"$field`"`r`n`r`n$($fields.Item($field))")
}
$sw.Close()
}
# Archivos binarios
if ($files.Length -gt 0) {
$files | % {
$sw = New-Object System.IO.StreamWriter($tempFile, $true, $UTF8woBOM)
$fileName = [System.IO.Path]::GetFileName($_)
$sw.Write("`r`n--$boundary`r`nContent-Disposition: form-data;name=`"upload_files`";filename=`"$fileName`"")
$sw.Write("`r`nContent-Type: application/octet-stream`r`n`r`n")
$sw.Close()
$fs = New-Object System.IO.FileStream($tempFile, [System.IO.FileMode]::Append)
$bw = New-Object System.IO.BinaryWriter($fs)
$fileBinary = [System.IO.File]::ReadAllBytes($_)
$bw.Write($fileBinary)
$bw.Close()
}
}
$sw = New-Object System.IO.StreamWriter($tempFile, $true, $UTF8woBOM)
$sw.Write("`r`n--$boundary--`r`n")
$sw.Close()
$tempFile
}