我使用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);
}
任何人都可以解决这个问题吗?提前谢谢!
答案 0 :(得分: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);
}
}
答案 1 :(得分:1)
@ Brajesh的回答对我很有帮助,但我需要一个.NET Core解决方案。特别是,我发现.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;
}
}