如何在 C# 中上传带有 multipart-HTML-Post 的 pdf?
How to upload a pdf with a multipart-HTML-Post in C#?
这里 我创建了一些代码,用于在 vba.
中上传带有 multipart-HTML-Post 的 pdf
这是我使用的代码:
Public Function sap_addTest(ByVal par_objectID As String, ByVal par_description As String, ByVal par_filename As String) As Integer
Dim ls_param As String
Dim text As String
Dim line As String
Dim url As String
Dim web As MSXML2.XMLHTTP60
url = "http://someurl.xml"
Set web = CreateObject("MSXML2.XMLHTTP")
Call web.Open("POST", url, False)
Const Boundary As String = "AaB03x"
Call web.setRequestHeader("content-type", "multipart/form-data;boundary=" & Boundary)
Call web.setRequestHeader("ws-callingapplication", sys_db)
Call web.setRequestHeader("Connection", "Keep-Alive")
Call web.setRequestHeader("cache-control", "no-cache")
Dim baBuffer() As Byte
Dim bytData
Dim bytPayLoad
With CreateObject("ADODB.Stream")
.Type = 1
.Mode = 3
.Open
.LoadFromFile par_filename
bytData = .Read
End With
With CreateObject("ADODB.Stream")
.Mode = 3
.Charset = "Windows-1252"
.Open
.Type = 2
.WriteText vbNewLine & "--" & Boundary & vbNewLine & "Content-Disposition: form-data; name=""object_id""" & vbNewLine & vbNewLine & par_objectID
.WriteText vbNewLine & "--" & Boundary & vbNewLine & "Content-Disposition: form-data; name=""description""" & vbNewLine & vbNewLine & par_description
.WriteText vbNewLine & "--" & Boundary & vbNewLine & "Content-Disposition: form-data; name=""file""; filename=""" & par_filename & """" & vbNewLine
.WriteText vbNewLine
.Position = 0
.Type = 1
.Position = .Size
.Write bytData
.Position = 0
.Type = 2
.Position = .Size
.WriteText vbNewLine & vbNewLine & "--" & Boundary & "--" & vbNewLine
.Position = 0
.Type = 1
bytPayLoad = .Read
End With
Call web.Send(bytPayLoad)
'Debug.Print web.status
'Debug.Print web.responseText
End Function
但现在我必须在 C# 中做同样的事情。我可能使用 HttpWebRequest 而不是 XMLHTTP。但是我的问题是如何替换ADODB.Stream? System.IO.Stream 似乎没有我使用的 functions/properties(模式、类型、WriteText、字符集)。这是我现在使用的代码:
public void Upload(ICommandLineInfo info)
{
var webRequest = HttpWebRequest.Create(info.Url) as HttpWebRequest;
const string HTTPBoundary = "AaB03x";
webRequest.ContentType = "multipart/form-data;boundary=" + HTTPBoundary;
const string HTTPHeaderCallingApplicationName = "ws-callingapplication";
webRequest.Headers.Add(HTTPHeaderCallingApplicationName, info.CallingApplication);
webRequest.KeepAlive = true;
const string HTTPHeaderCacheControlName = "cache-control";
const string HTTPHeaderValueCacheControlNo = "no-cache";
webRequest.Headers.Add(HTTPHeaderCacheControlName, HTTPHeaderValueCacheControlNo);
webRequest.Method = "POST";
using (Stream requestStream = webRequest.GetRequestStream())
{
//Here I dont know how to write my file into the Request stream
//requestStream.Write(bytes, 0, bytes.Length); ?
requestStream.Close();
}
var response = (HttpWebResponse)webRequest.GetResponse();
}
我找到了这个 multipart post -- uploading a file,但是代码是 Java 并且 C# 中缺少几个部分(如 HttpPost、MultipartEntityBuilder 等)
那么如何构建请求流的字节数组呢?
更新:
这是我目前使用的代码:
public void Upload(ICommandLineInfo info)
{
var webRequest = HttpWebRequest.Create(info.Url) as HttpWebRequest;
const string HTTPBoundary = "AaB03x";
webRequest.ContentType = "multipart/form-data;boundary=" + HTTPBoundary;
const string HTTPHeaderCallingApplicationName = "ws-callingapplication";
webRequest.Headers.Add(HTTPHeaderCallingApplicationName, info.CallingApplication);
webRequest.KeepAlive = true;
webRequest.UseDefaultCredentials = true;
webRequest.PreAuthenticate = true;
webRequest.Credentials = CredentialCache.DefaultCredentials;
const string HTTPHeaderCacheControlName = "cache-control";
const string HTTPHeaderValueCacheControlNo = "no-cache";
webRequest.Headers.Add(HTTPHeaderCacheControlName, HTTPHeaderValueCacheControlNo);
webRequest.Method = "POST";
Stream requestStream = webRequest.GetRequestStream();
string stringInfo = "";
stringInfo = stringInfo + Environment.NewLine + "--" + HTTPBoundary + Environment.NewLine + "Content-Disposition: form-data; name=\"itemName\"" + Environment.NewLine + Path.GetFileName(info.Filename);
stringInfo = stringInfo + Environment.NewLine + "--" + HTTPBoundary + Environment.NewLine + "Content-Disposition: form-data; name=\"parentNickname\"" + Environment.NewLine + info.ParentNickname;
stringInfo = stringInfo + Environment.NewLine + "--" + HTTPBoundary + Environment.NewLine + "Content-Disposition: form-data; name=\"file\"; filename=\"" + info.Filename + "\"" + Environment.NewLine + Environment.NewLine;
var stringBytes = Encoding.ASCII.GetBytes(stringInfo);
requestStream.Write(stringBytes, 0, stringBytes.Length);
var fileBytes = File.ReadAllBytes(info.Filename);
requestStream.Write(stringBytes, 0, stringBytes.Length);
string endInfo = Environment.NewLine+ Environment.NewLine + "--" + HTTPBoundary + "--" + Environment.NewLine;
var endBytes = Encoding.ASCII.GetBytes(endInfo);
requestStream.Write(endBytes, 0, endBytes.Length);
requestStream.Flush();
requestStream.Close();
var response = (HttpWebResponse)webRequest.GetResponse();
}
不幸的是 webRequest.GetResponse() 抛出异常:
The remoteserver returned an error. 500: Internal server error
我的大学 - 负责服务器部分 - 告诉我他收到 "unexpected end of stream"-错误。
好像c#也有ADODB Stream。在参考文献中:"ADODB"。所以我的最终代码如下所示:
public void Upload(ICommandLineInfo info)
{
var webRequest = HttpWebRequest.Create(info.Url) as HttpWebRequest;
const string HTTPBoundary = "AaB03x";
webRequest.ContentType = "multipart/form-data;boundary=" + HTTPBoundary;
const string HTTPHeaderCallingApplicationName = "ws-callingapplication";
webRequest.Headers.Add(HTTPHeaderCallingApplicationName, info.CallingApplication);
webRequest.KeepAlive = true;
webRequest.UseDefaultCredentials = true;
webRequest.PreAuthenticate = true;
webRequest.Credentials = CredentialCache.DefaultCredentials;
const string HTTPHeaderCacheControlName = "cache-control";
const string HTTPHeaderValueCacheControlNo = "no-cache";
webRequest.Headers.Add(HTTPHeaderCacheControlName, HTTPHeaderValueCacheControlNo);
webRequest.Method = "POST";
ADODB.Stream fileStream = new ADODB.Stream();
fileStream.Type = ADODB.StreamTypeEnum.adTypeBinary;
fileStream.Mode = ADODB.ConnectModeEnum.adModeReadWrite;
fileStream.Open();
fileStream.LoadFromFile(info.Filename);
var byteData = fileStream.Read();
fileStream.Close();
ADODB.Stream mixedStream = new ADODB.Stream();
mixedStream.Mode = ADODB.ConnectModeEnum.adModeReadWrite;
mixedStream.Charset = "utf-8";
mixedStream.Open();
mixedStream.Type = ADODB.StreamTypeEnum.adTypeText;
mixedStream.WriteText(Environment.NewLine + "--" + HTTPBoundary + Environment.NewLine + "Content-Disposition: form-data; name=\"itemName\"" + Environment.NewLine + Environment.NewLine + Path.GetFileName(info.Filename));
mixedStream.WriteText(Environment.NewLine + "--" + HTTPBoundary + Environment.NewLine + "Content-Disposition: form-data; name=\"parentNickname\"" + Environment.NewLine + Environment.NewLine + info.ParentNickname);
mixedStream.WriteText(Environment.NewLine + "--" + HTTPBoundary + Environment.NewLine + "Content-Disposition: form-data; name=\"file\"; filename=\"" + info.Filename + "\"" + Environment.NewLine);
mixedStream.WriteText(Environment.NewLine);
mixedStream.Position = 0;
mixedStream.Type = ADODB.StreamTypeEnum.adTypeBinary;
mixedStream.Position = mixedStream.Size;
mixedStream.Write(byteData);
byteData = null;
mixedStream.Position = 0;
mixedStream.Type = ADODB.StreamTypeEnum.adTypeText;
mixedStream.Position = mixedStream.Size;
mixedStream.WriteText(Environment.NewLine + Environment.NewLine + "--" + HTTPBoundary + "--" + Environment.NewLine);
mixedStream.Position = 0;
mixedStream.Type = ADODB.StreamTypeEnum.adTypeBinary;
var read = mixedStream.Read();
webRequest.ContentLength = read.Length;
Stream requestStream = webRequest.GetRequestStream();
requestStream.Write(read, 0, read.Length);
requestStream.Close();
try
{
var response = (HttpWebResponse)webRequest.GetResponse();
}
catch (WebException exception)
{
using (var reader = new System.IO.StreamReader(exception.Response.GetResponseStream()))
{
string responseText = reader.ReadToEnd();
}
}
}
这似乎不是在 C# 中执行此操作的完美方法,但它确实有效。
这里
这是我使用的代码:
Public Function sap_addTest(ByVal par_objectID As String, ByVal par_description As String, ByVal par_filename As String) As Integer
Dim ls_param As String
Dim text As String
Dim line As String
Dim url As String
Dim web As MSXML2.XMLHTTP60
url = "http://someurl.xml"
Set web = CreateObject("MSXML2.XMLHTTP")
Call web.Open("POST", url, False)
Const Boundary As String = "AaB03x"
Call web.setRequestHeader("content-type", "multipart/form-data;boundary=" & Boundary)
Call web.setRequestHeader("ws-callingapplication", sys_db)
Call web.setRequestHeader("Connection", "Keep-Alive")
Call web.setRequestHeader("cache-control", "no-cache")
Dim baBuffer() As Byte
Dim bytData
Dim bytPayLoad
With CreateObject("ADODB.Stream")
.Type = 1
.Mode = 3
.Open
.LoadFromFile par_filename
bytData = .Read
End With
With CreateObject("ADODB.Stream")
.Mode = 3
.Charset = "Windows-1252"
.Open
.Type = 2
.WriteText vbNewLine & "--" & Boundary & vbNewLine & "Content-Disposition: form-data; name=""object_id""" & vbNewLine & vbNewLine & par_objectID
.WriteText vbNewLine & "--" & Boundary & vbNewLine & "Content-Disposition: form-data; name=""description""" & vbNewLine & vbNewLine & par_description
.WriteText vbNewLine & "--" & Boundary & vbNewLine & "Content-Disposition: form-data; name=""file""; filename=""" & par_filename & """" & vbNewLine
.WriteText vbNewLine
.Position = 0
.Type = 1
.Position = .Size
.Write bytData
.Position = 0
.Type = 2
.Position = .Size
.WriteText vbNewLine & vbNewLine & "--" & Boundary & "--" & vbNewLine
.Position = 0
.Type = 1
bytPayLoad = .Read
End With
Call web.Send(bytPayLoad)
'Debug.Print web.status
'Debug.Print web.responseText
End Function
但现在我必须在 C# 中做同样的事情。我可能使用 HttpWebRequest 而不是 XMLHTTP。但是我的问题是如何替换ADODB.Stream? System.IO.Stream 似乎没有我使用的 functions/properties(模式、类型、WriteText、字符集)。这是我现在使用的代码:
public void Upload(ICommandLineInfo info)
{
var webRequest = HttpWebRequest.Create(info.Url) as HttpWebRequest;
const string HTTPBoundary = "AaB03x";
webRequest.ContentType = "multipart/form-data;boundary=" + HTTPBoundary;
const string HTTPHeaderCallingApplicationName = "ws-callingapplication";
webRequest.Headers.Add(HTTPHeaderCallingApplicationName, info.CallingApplication);
webRequest.KeepAlive = true;
const string HTTPHeaderCacheControlName = "cache-control";
const string HTTPHeaderValueCacheControlNo = "no-cache";
webRequest.Headers.Add(HTTPHeaderCacheControlName, HTTPHeaderValueCacheControlNo);
webRequest.Method = "POST";
using (Stream requestStream = webRequest.GetRequestStream())
{
//Here I dont know how to write my file into the Request stream
//requestStream.Write(bytes, 0, bytes.Length); ?
requestStream.Close();
}
var response = (HttpWebResponse)webRequest.GetResponse();
}
我找到了这个 multipart post -- uploading a file,但是代码是 Java 并且 C# 中缺少几个部分(如 HttpPost、MultipartEntityBuilder 等)
那么如何构建请求流的字节数组呢?
更新:
这是我目前使用的代码:
public void Upload(ICommandLineInfo info)
{
var webRequest = HttpWebRequest.Create(info.Url) as HttpWebRequest;
const string HTTPBoundary = "AaB03x";
webRequest.ContentType = "multipart/form-data;boundary=" + HTTPBoundary;
const string HTTPHeaderCallingApplicationName = "ws-callingapplication";
webRequest.Headers.Add(HTTPHeaderCallingApplicationName, info.CallingApplication);
webRequest.KeepAlive = true;
webRequest.UseDefaultCredentials = true;
webRequest.PreAuthenticate = true;
webRequest.Credentials = CredentialCache.DefaultCredentials;
const string HTTPHeaderCacheControlName = "cache-control";
const string HTTPHeaderValueCacheControlNo = "no-cache";
webRequest.Headers.Add(HTTPHeaderCacheControlName, HTTPHeaderValueCacheControlNo);
webRequest.Method = "POST";
Stream requestStream = webRequest.GetRequestStream();
string stringInfo = "";
stringInfo = stringInfo + Environment.NewLine + "--" + HTTPBoundary + Environment.NewLine + "Content-Disposition: form-data; name=\"itemName\"" + Environment.NewLine + Path.GetFileName(info.Filename);
stringInfo = stringInfo + Environment.NewLine + "--" + HTTPBoundary + Environment.NewLine + "Content-Disposition: form-data; name=\"parentNickname\"" + Environment.NewLine + info.ParentNickname;
stringInfo = stringInfo + Environment.NewLine + "--" + HTTPBoundary + Environment.NewLine + "Content-Disposition: form-data; name=\"file\"; filename=\"" + info.Filename + "\"" + Environment.NewLine + Environment.NewLine;
var stringBytes = Encoding.ASCII.GetBytes(stringInfo);
requestStream.Write(stringBytes, 0, stringBytes.Length);
var fileBytes = File.ReadAllBytes(info.Filename);
requestStream.Write(stringBytes, 0, stringBytes.Length);
string endInfo = Environment.NewLine+ Environment.NewLine + "--" + HTTPBoundary + "--" + Environment.NewLine;
var endBytes = Encoding.ASCII.GetBytes(endInfo);
requestStream.Write(endBytes, 0, endBytes.Length);
requestStream.Flush();
requestStream.Close();
var response = (HttpWebResponse)webRequest.GetResponse();
}
不幸的是 webRequest.GetResponse() 抛出异常:
The remoteserver returned an error. 500: Internal server error
我的大学 - 负责服务器部分 - 告诉我他收到 "unexpected end of stream"-错误。
好像c#也有ADODB Stream。在参考文献中:"ADODB"。所以我的最终代码如下所示:
public void Upload(ICommandLineInfo info)
{
var webRequest = HttpWebRequest.Create(info.Url) as HttpWebRequest;
const string HTTPBoundary = "AaB03x";
webRequest.ContentType = "multipart/form-data;boundary=" + HTTPBoundary;
const string HTTPHeaderCallingApplicationName = "ws-callingapplication";
webRequest.Headers.Add(HTTPHeaderCallingApplicationName, info.CallingApplication);
webRequest.KeepAlive = true;
webRequest.UseDefaultCredentials = true;
webRequest.PreAuthenticate = true;
webRequest.Credentials = CredentialCache.DefaultCredentials;
const string HTTPHeaderCacheControlName = "cache-control";
const string HTTPHeaderValueCacheControlNo = "no-cache";
webRequest.Headers.Add(HTTPHeaderCacheControlName, HTTPHeaderValueCacheControlNo);
webRequest.Method = "POST";
ADODB.Stream fileStream = new ADODB.Stream();
fileStream.Type = ADODB.StreamTypeEnum.adTypeBinary;
fileStream.Mode = ADODB.ConnectModeEnum.adModeReadWrite;
fileStream.Open();
fileStream.LoadFromFile(info.Filename);
var byteData = fileStream.Read();
fileStream.Close();
ADODB.Stream mixedStream = new ADODB.Stream();
mixedStream.Mode = ADODB.ConnectModeEnum.adModeReadWrite;
mixedStream.Charset = "utf-8";
mixedStream.Open();
mixedStream.Type = ADODB.StreamTypeEnum.adTypeText;
mixedStream.WriteText(Environment.NewLine + "--" + HTTPBoundary + Environment.NewLine + "Content-Disposition: form-data; name=\"itemName\"" + Environment.NewLine + Environment.NewLine + Path.GetFileName(info.Filename));
mixedStream.WriteText(Environment.NewLine + "--" + HTTPBoundary + Environment.NewLine + "Content-Disposition: form-data; name=\"parentNickname\"" + Environment.NewLine + Environment.NewLine + info.ParentNickname);
mixedStream.WriteText(Environment.NewLine + "--" + HTTPBoundary + Environment.NewLine + "Content-Disposition: form-data; name=\"file\"; filename=\"" + info.Filename + "\"" + Environment.NewLine);
mixedStream.WriteText(Environment.NewLine);
mixedStream.Position = 0;
mixedStream.Type = ADODB.StreamTypeEnum.adTypeBinary;
mixedStream.Position = mixedStream.Size;
mixedStream.Write(byteData);
byteData = null;
mixedStream.Position = 0;
mixedStream.Type = ADODB.StreamTypeEnum.adTypeText;
mixedStream.Position = mixedStream.Size;
mixedStream.WriteText(Environment.NewLine + Environment.NewLine + "--" + HTTPBoundary + "--" + Environment.NewLine);
mixedStream.Position = 0;
mixedStream.Type = ADODB.StreamTypeEnum.adTypeBinary;
var read = mixedStream.Read();
webRequest.ContentLength = read.Length;
Stream requestStream = webRequest.GetRequestStream();
requestStream.Write(read, 0, read.Length);
requestStream.Close();
try
{
var response = (HttpWebResponse)webRequest.GetResponse();
}
catch (WebException exception)
{
using (var reader = new System.IO.StreamReader(exception.Response.GetResponseStream()))
{
string responseText = reader.ReadToEnd();
}
}
}
这似乎不是在 C# 中执行此操作的完美方法,但它确实有效。