如何在 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# 中执行此操作的完美方法,但它确实有效。