C# 是否使用Windows Universal App中的HttpClient将文件上载到WebDAV?

C# 是否使用Windows Universal App中的HttpClient将文件上载到WebDAV?,c#,win-universal-app,C#,Win Universal App,我使用WebClient上传了一个标题很少的文件,效果非常好。但现在我正在使用HttpClient创建一个通用应用程序。我不明白如何将文件路径添加到请求头。请参阅以下代码: public async void testUploadFile() { string url = "http://localhost/webdav/"; string filepath = @"C:\mydata\file-1.txt"; string resource_name = Path.Ge

我使用
WebClient
上传了一个标题很少的文件,效果非常好。但现在我正在使用
HttpClient
创建一个通用应用程序。我不明白如何将文件路径添加到请求头。请参阅以下代码:

public async void testUploadFile()
{
    string url = "http://localhost/webdav/";
    string filepath = @"C:\mydata\file-1.txt";
    string resource_name = Path.GetFileName(filepath);
    url += resource_name;
    HttpMultipartFormDataContent multipart = new HttpMultipartFormDataContent();
    multipart.Headers.Add("RequestId", "abc");
    multipart.Headers.Add("UserId", "apple");
    multipart.Headers.Add("SessionId", "ssdfsd22");
    Stream stream = new System.IO.MemoryStream();
    HttpStreamContent streamContent = new HttpStreamContent(stream.AsInputStream());
    multipart.Add(streamContent);
    httpClient = new HttpClient();

    HttpResponseMessage respMesg =await httpClient.PutAsync(new Uri(url), multipart);
    Debug.WriteLine(respMesg.Content);
}

有人能解决这个问题吗?提前谢谢你

以下代码适用于一次性上载:

public async void testFileUploadWebDAV()
{      
    string url = "http://localhost/webdav/";
    string userId = "xxx";
    string sessionId = "yyy";

    var filter = new HttpBaseProtocolFilter(); 
    filter.IgnorableServerCertificateErrors.Add(ChainValidationResult.Untrusted);
    filter.IgnorableServerCertificateErrors.Add(ChainValidationResult.IncompleteChain);

    var filePicker = new FileOpenPicker();
    filePicker.FileTypeFilter.Add("*");
    filePicker.SuggestedStartLocation = PickerLocationId.DocumentsLibrary;
    StorageFile file = await filePicker.PickSingleFileAsync();
    url += file.Name;

    httpClient = new HttpClient(filter);
    msg = new HttpRequestMessage(new HttpMethod("PUT"), new Uri(url));

    httpClient.DefaultRequestHeaders.Add("RequestId", file.DisplayName);
    httpClient.DefaultRequestHeaders.Add("UserId", userId);
    httpClient.DefaultRequestHeaders.Add("SessionId", sessionId);
    httpClient.DefaultRequestHeaders.Add("ContentType", file.ContentType);

    Certificate cert = msg.TransportInformation.ServerCertificate;
    //-----------------ADD FILE CONTENT TO BODY-----------

    HttpStreamContent content = new HttpStreamContent(await file.OpenReadAsync());
    try
    {
        HttpResponseMessage httpResponseContent = await httpClient.PutAsync(new Uri(url), content);
        Debug.WriteLine(httpResponseContent.ToString());
        if (httpResponseContent.IsSuccessStatusCode)
        {                        
            msg.Dispose();                        
            httpClient.Dispose();
        }
    }
    catch (Exception ex)
    {
        Debug.WriteLine(ex.Message);
    }                    
}

@Brajesh的回答对我非常有帮助,但我需要一个.NET核心解决方案。特别是,我发现.NET Core中的编码支持存在一些问题,因此我不能将
StreamContent
传递到
httpClient.PutAsync
方法中。请参见下面的.NET Core等效版本:

public static async void writeToWebDAV(string sourceFilename, Stream httpStream)
{
    //As described above, decoding must be forced as UTF8 default returns some strange results
    var content = Encoding.GetEncoding("iso-8859-1").GetString(readToEnd(httpStream));
    using (var httpClient = new HttpClient())
    {
        httpClient.DefaultRequestHeaders.Add("RequestId", sourceFilename);
        //Be sure user:pass is in Base64 encoding, can use this resource https://www.base64encode.org/
        httpClient.DefaultRequestHeaders.Add("Authorization", "Basic dXNlcjpwYXNzd29yZA==");
        StringContent c = new StringContent(content, Encoding.UTF8);
        try
        {
            HttpResponseMessage httpResponseContent = await httpClient.PutAsync(
                new Uri(Path.Combine(@"https://randomhost.com:5009/shareFolder", sourceFilename)), c);
            if (httpResponseContent.IsSuccessStatusCode)
                httpClient.Dispose();
            else
            {
                try
                {
                    //occasionally the server will respond with the WWW-Authenticate header in which case you need to re-PUT the file
                    //described here: https://stackoverflow.com/questions/32393846/webdav-return-401-how-to-authenticate
                    HttpResponseMessage httpResponseContent = await httpClient.PutAsync(
                        new Uri(Path.Combine(@"https://randomhost.com:5009/shareFolder", sourceFilename)), c);
                    if (httpResponseContent.IsSuccessStatusCode)
                        httpClient.Dispose();
                    else if (httpResponseContent.StatusCode.ToString() == "401")
                        Console.WriteLine("WebDAV Authentication Error...");
                }
                catch (Exception ex)
                { Console.WriteLine(ex.Message); }
            }
        }
        catch (Exception ex)
        { Console.WriteLine(ex.Message); }
    }
}

//Taken from StackOverflow: https://stackoverflow.com/questions/1080442/how-to-convert-an-stream-into-a-byte-in-c
public static byte[] readToEnd(Stream stream)
{
    long originalPosition = 0;

    if (stream.CanSeek)
    {
        originalPosition = stream.Position;
        stream.Position = 0;
    }
    try
    {
        byte[] readBuffer = new byte[4096];
        int totalBytesRead = 0;
        int bytesRead;

        while ((bytesRead = stream.Read(readBuffer, totalBytesRead, readBuffer.Length - totalBytesRead)) > 0)
        {
            totalBytesRead += bytesRead;
            if (totalBytesRead == readBuffer.Length)
            {
                int nextByte = stream.ReadByte();
                if (nextByte != -1)
                {
                    byte[] temp = new byte[readBuffer.Length * 2];
                    Buffer.BlockCopy(readBuffer, 0, temp, 0, readBuffer.Length);
                    Buffer.SetByte(temp, totalBytesRead, (byte)nextByte);
                    readBuffer = temp;
                    totalBytesRead++;
                }
            }
        }
        byte[] buffer = readBuffer;
        if (readBuffer.Length != totalBytesRead)
        {
            buffer = new byte[totalBytesRead];
            Buffer.BlockCopy(readBuffer, 0, buffer, 0, totalBytesRead);
        }
        return buffer;
    }
    finally
    {
        if (stream.CanSeek)
            stream.Position = originalPosition;
    }
}