未保存到硬盘直接上传图片的VB.NET代码问题求助
问题:截图直接上传(不存硬盘)失败,存硬盘后上传正常,求排查
我想实现不把截图保存到硬盘直接上传(提升性能),写了下面的代码,但无法正常工作;而先存硬盘再上传的代码是能正常运行的。请问我的直接上传代码里遗漏了什么?
直接上传(无法正常运行)的代码
Public Shared Function ConvertToByteArray(ByVal value As Bitmap) As Byte() Dim bitmapBytes As Byte() Using stream As New System.IO.MemoryStream value.Save(stream, System.Drawing.Imaging.ImageFormat.Png) bitmapBytes = stream.ToArray End Using Return bitmapBytes End Function Public Sub screenCapture() Dim bmp As Bitmap = Screen_Capture() 'api call BitBlt Dim data As Byte() = ConvertToByteArray(bmp) Dim myWebClient As New System.Net.WebClient() myWebClient.Headers.Add("Content-Type", "application/x-www-form-urlencoded") Dim responseArray As Byte() = myWebClient.UploadData("https://xxx.php", "Post", data) Dim response As String = System.Text.Encoding.ASCII.GetString(responseArray) MsgBox(response) End Sub
存硬盘后上传(正常运行)的代码
Public Sub screenCapture() Dim bmp As Bitmap = Screen_Capture() 'api call BitBlt Dim userName As String = Environment.UserName Dim savePath As String = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) Dim captureSavePath As String = String.Format("{0}\SID\{1}\capture.png", savePath, userName) bmp.Save(captureSavePath) Dim myWebClient As New System.Net.WebClient() Dim responseArray As Byte() = myWebClient.UploadFile("https://xxx.php", "Post", captureSavePath) 'Dim response As String = System.Text.Encoding.ASCII.GetString(responseArray) 'MsgBox(response) End Sub
问题排查与修复方案
核心问题在于请求格式不匹配:
UploadFile方法会自动把文件包装成符合HTTP文件上传标准的multipart/form-data格式,后端的PHP代码应该是通过$_FILES来接收文件,这种格式刚好匹配;- 而你用
UploadData时,错误设置了Content-Type: application/x-www-form-urlencoded(这是普通表单键值对的编码格式),并且直接把PNG字节裸传,后端无法识别为合法的文件上传请求。
修复方法二选一:
方法1:手动构建multipart/form-data请求上传字节流
这种方式贴合后端原有的$_FILES接收逻辑,不需要修改后端:
Public Sub screenCapture() Dim bmp As Bitmap = Screen_Capture() Dim data As Byte() = ConvertToByteArray(bmp) Dim boundary As String = "---------------------------" & DateTime.Now.Ticks.ToString("x") Dim webClient As New WebClient() webClient.Headers.Add("Content-Type", "multipart/form-data; boundary=" & boundary) ' 构建multipart请求内容 Using ms As New MemoryStream() Dim boundaryBytes As Byte() = Encoding.ASCII.GetBytes(vbCrLf & "--" & boundary & vbCrLf) Dim formDataTemplate As String = "Content-Disposition: form-data; name=""file""; filename=""capture.png""" & vbCrLf & "Content-Type: image/png" & vbCrLf & vbCrLf ' 写入边界和表单头 ms.Write(boundaryBytes, 0, boundaryBytes.Length) Dim formDataBytes As Byte() = Encoding.UTF8.GetBytes(formDataTemplate) ms.Write(formDataBytes, 0, formDataBytes.Length) ' 写入PNG字节 ms.Write(data, 0, data.Length) ' 写入结束边界 Dim endBoundaryBytes As Byte() = Encoding.ASCII.GetBytes(vbCrLf & "--" & boundary & "--" & vbCrLf) ms.Write(endBoundaryBytes, 0, endBoundaryBytes.Length) ' 上传数据 Dim responseArray As Byte() = webClient.UploadData("https://xxx.php", "POST", ms.ToArray()) Dim response As String = Encoding.UTF8.GetString(responseArray) MsgBox(response) End Using End Sub
方法2:修改后端PHP代码接收原始字节流
如果后端可以修改,直接读取请求体的原始字节来保存文件,此时前端只需调整Content-Type:
' 修改screenCapture方法中的Header和上传逻辑 Public Sub screenCapture() Dim bmp As Bitmap = Screen_Capture() Dim data As Byte() = ConvertToByteArray(bmp) Dim myWebClient As New System.Net.WebClient() myWebClient.Headers.Add("Content-Type", "image/png") ' 改为正确的MIME类型 Dim responseArray As Byte() = myWebClient.UploadData("https://xxx.php", "Post", data) Dim response As String = System.Text.Encoding.UTF8.GetString(responseArray) ' 建议用UTF8而非ASCII,避免乱码 MsgBox(response) End Sub
对应的PHP后端示例:
// 读取原始请求体 $fileData = file_get_contents('php://input'); // 保存文件 file_put_contents('capture.png', $fileData); echo "上传成功";
内容的提问来源于stack exchange,提问作者Tanmay Chakraborty
相关产品推荐
相关产品推荐

