2015-09-28 84 views
0

我使用WebClient来上传一个头文件很少的文件,它的工作完美。但是现在我正在使用HttpClient创建一个通用应用程序。我不理解如何将文件路径添加到请求标头。请看下面的代码:在Windows通用应用程序中使用HttpClient PUT将文件上传到WebDAV?

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); 
} 

任何人都可以解决这个问题吗?先谢谢你!

回答

1

下面的代码适用于一次性上传:

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); 
    }      
} 
0

@ 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; 
    } 
} 
相关问题