我们可以使用以下curl命令将包含压缩LDIF文件的ZIP文件上传到小型Spring Boot应用程序:
curl -k -X POST -F“file=@/dev/Cservice.zip;type=application/zip” https://sag01.xxaws.com:10006/Cservice --cert /dev/axis.pem --key /gx/dev/axis.key
Spring Boot 应用程序接收 ZIPPED LDIF 文件,将其解压缩,然后根据解压缩的 LDIF 文件中的行进行一些处理。
但在某些环境中,他们没有Linux,因此无法使用Curl,所以我现在尝试实现一个powershell脚本来执行与curl命令相同的上传,并且我发现这个线程较旧的Stackoverflow线程(Powershell无法使用多部分表单数据将超过 ~50MB 的 zip 文件上传到 REST API),同时搜索如何实现这一目标。
我一直在尝试使用“Ralph”在较早的 SO 线程中发布的第一个 powershell 脚本,在Powershell 无法使用 Multipart form-data to REST API 上传超过 ~50MB 的 zip 文件),但针对我们的环境进行了修改(主要区别在于我们使用证书身份验证)_
这是我目前在 powershell 上的尝试:
# From: https://stackoverflow.com/questions/69038508/powershell-is-unable-to-upload-zip-file-over-50mb-using-multipart-form-data-to
Write-output "RUNNING: 8from-stackoverflow.ps1"
$Uri = 'https://sag01.gxaws.com:10006/CService'
$fileBytes = [System.IO.File]::ReadAllBytes("G:\Dev\CService.zip");
$enc = [System.Text.Encoding]::GetEncoding('utf-8')
$fileEnc = $enc.GetString($fileBytes)
Invoke-WebRequest -Uri $Uri -method POST -TimeoutSec 999999 -Certificate (Get-PfxCertificate axisWithKey.pfx) -SkipCertificateCheck `
-Headers @{ "accept"="*/*"} `
-ContentType "multipart/form-data; boundary=WebKitFormBoundaryT2XycANuthCIUwGk" `
-Body ([System.Text.Encoding]::UTF8.GetBytes("--WebKitFormBoundaryT2XycANuthCIUwGk$([char]13)$([char]10)Content-Disposition: form-data; name=`"file`"; filename=`"CService.zip`"$([char]13)$([char]10)Content-Type: application/x-zip-compressed$([char]13)$([char]10)$([char]13)$([char]10))$fileEnc($([char]13)$([char]10)-- WebKitFormBoundaryT2XycANuthCIUwGk--$([char]13)$([char]10)"))
当我运行上面的 powershell 脚本时,我跟踪正在接收上传的应用程序日志,看起来 powershell 脚本正在尝试上传“CService.zip”文件,并且 spring boot 应用程序正在看到上传请求,我可以看到似乎是 zip 文件的二进制数据。这是 powershell 脚本运行时 ZIP 文件日志记录的开始(我希望出现下面的行):
--WebKitFormBoundaryT2XycANuthCIUwGk
Content-Disposition: form-data; name="file"; filename="CService.zip"
Content-Type: application/x-zip-compressed
�*T*�d~��tb����Z▒¿½n�no4�lÏ¢S���y~t�y�r�a��ï¿m?m�í������l�_���^^���y����
然而,在应用程序收到 ZIP 文件后,它应该解压缩内容,然后记录行,但它似乎无法做到这一点:
2024-03-14 18:12:58,048 DEBUG m.n.g.m.c.u.StringUtils [https-jsse-nio-8888-exec-2] LDIF before reMap method:
2024-03-14 18:12:58,048 DEBUG m.n.g.m.c.u.StringUtils [https-jsse-nio-8888-exec-2] LDIF after reMap method:
2024-03-14 18:12:58,048 DEBUG m.n.g.m.c.s.LDAPService [https-jsse-nio-8888-exec-2] Lidf entries count = 0
当我运行工作的 Curl 命令时,我查看了相同的服务器端应用程序日志记录,并且它输出二进制数据的日志记录看起来与我运行 powershell 脚本时的日志记录完全不同。
以下是运行 curl 时的日志记录片段:
2024-03-14 18:38:50,916 DEBUG o.a.j.l.DirectJDKLog [https-jsse-nio-8888-exec-9] Received [--------------------------a18e445ef02489d2^M
Content-Disposition: form-data; name="file"; filename="CService.zip"^M
Content-Type: application/zip^M
^M
PK^C^D^T^@^@^@^H^@QmuVe^XÂ<86>(^O^@^@'~^B^@^S^@^@^@CService.ldif<9a>]kT ^VEß^Cù^Où^A*u¿êC^P&¦¡q µiõa<9e><86>2Vb^M±*T*Íd~ýÜtb<8e><8c>û<84>^^Z^O^[ön<90>no4®lÏ¢S¬ú¸y~tºyñrûaòå<9f>é³^?m?m<9e>í<9e><9d>ÿûr^?^Z<8f><9f>l¯_üºÚ^^¬<9e>¼yÿâõÏÇ·ÿúiûÓ<93>7/Þ?{ûìèçíï«Ýæój³^?ròâýÛÃ<83
另外,我注意到运行 powershell 时的内容长度大约是运行 Curl 时的长度的两倍。
所以我认为我一定是对 powershell 脚本中编码 ZIP 文件的部分做错了什么?或者,Curl 上传到 Spring Boot 应用程序可能有效,因为 Curl 正在执行不同类型的编码或其他操作?
我希望这里有人能够提供帮助,因为我已经尝试让它工作几天了,而且我觉得我离解决方案越来越远,而不是更接近,所以我决定尝试在这里发帖。
如果有任何问题,请告诉我,我会尽力回答!
提前致谢,吉姆
编辑:这是根据 mklement0 的建议最终起作用的(在评论中):
#FROM: https://stackoverflow.com/questions/78162873/problem-trying-to-use-powershell-to-upload-a-zip-file-to-a-spring-boot-applicati
#and:
#FROM: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/invoke-webrequest?view=powershell-7.4#example-5-submit-a-multipart-form-data-file
$FilePath = 'G:\Dev\CService.zip'
$URL = 'https://sag02.xxaws.com:10006/CService'
Write-output "ZIP File: $FilePath"
Write-output "URL: $URL"
$FieldName = 'file'
$ContentType = 'application/zip'
$FileStream = [System.IO.FileStream]::new($filePath, [System.IO.FileMode]::Open)
$FileHeader = [System.Net.Http.Headers.ContentDispositionHeaderValue]::new('form-data')
$FileHeader.Name = $FieldName
$FileHeader.FileName = Split-Path -leaf $FilePath
$FileContent = [System.Net.Http.StreamContent]::new($FileStream)
$FileContent.Headers.ContentDisposition = $FileHeader
$FileContent.Headers.ContentType = [System.Net.Http.Headers.MediaTypeHeaderValue]::Parse($ContentType)
$MultipartContent = [System.Net.Http.MultipartFormDataContent]::new()
$MultipartContent.Add($FileContent)
$Response = Invoke-WebRequest -Body $MultipartContent -Method POST -Uri $URL -TimeoutSec 999999 -Certificate (Get-PfxCertificate geoaxisWithKey.pfx) -SkipCertificateCheck
Write-output $Response
前言:
可能不需要将您的
curl
调用转换为Invoke-WebRequest
等效的调用:curl.exe
( 和tar.exe
),因此您通常可以使用现有curl
命令(可能需要对 PowerShell 语法进行小调整) - 只需确保将可执行文件指定为curl.exe
,而不仅仅是curl
,因为后者是Invoke-WebRequest
Windows PowerShell 中 cmdlet的内置别名。如果您仍然想要/需要翻译,请继续阅读
Invoke-WebRequest
。以下内容改编自帮助主题的示例 5
Invoke-WebRequest
,该示例展示了如何以 multipart/form-data 提交方式上传给定文件(无论其内容如何,包括二进制内容):以下简化版本取自示例 6,也可以工作(我不清楚是否也必须显式指定媒体类型):
至于你尝试过的:
请注意,将任意二进制数据(本质上是字节数组)表示为 UTF-8 字符串基本上是不可能的,因为并非所有字节都是 UTF-8 中的有效字符,尤其是值 >=
0x80
(128
)的任意字节以下往返示例演示了这一点:
输出:
请注意无效的 UTF-8 字节如何在解码时
128
变成多个字节。具体来说,3 字节序列,
239
是Unicode 字符(REPLACMENT CHARACTER, )的编码,表示无效字符。191
189
�
U+FFFD