我尝试将文本文件从 WPF RESTful客户端上传到ASP .NET MVC WebAPI 2网站。
客户代码
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create("http://localhost:22678/api/Account/UploadFile?fileName=test.txt&description=MyDesc1");
request.Method = WebRequestMethods.Http.Post;
request.Headers.Add("Authorization", "Bearer " + tokenModel.ExternalAccessToken);
request.ContentType = "text/plain";
request.MediaType = "text/plain";
byte[] fileToSend = File.ReadAllBytes(@"E:\test.txt");
request.ContentLength = fileToSend.Length;
using (Stream requestStream = request.GetRequestStream())
{
// Send the file as body request.
requestStream.Write(fileToSend, 0, fileToSend.Length);
requestStream.Close();
}
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
Console.WriteLine("HTTP/{0} {1} {2}", response.ProtocolVersion, (int)response.StatusCode, response.StatusDescription);
WebAPI 2代码
[HttpPost]
[HostAuthentication(DefaultAuthenticationTypes.ExternalBearer)]
[Route("UploadFile")]
public void UploadFile(string fileName, string description, Stream fileContents)
{
byte[] buffer = new byte[32768];
MemoryStream ms = new MemoryStream();
int bytesRead, totalBytesRead = 0;
do
{
bytesRead = fileContents.Read(buffer, 0, buffer.Length);
totalBytesRead += bytesRead;
ms.Write(buffer, 0, bytesRead);
} while (bytesRead > 0);
var data = ms.ToArray() ;
ms.Close();
Debug.WriteLine("Uploaded file {0} with {1} bytes", fileName, totalBytesRead);
}
所以..在客户端代码下我面临异常
远程服务器返回错误:(415)不支持的媒体类型。
有什么线索我缺少什么?
答案 0 :(得分:13)
您正在设置ContentType = "text/plain"
,此设置会驱动格式化程序选择。请查看Media Formatters了解详情。
摘录:
在Web API中,媒体类型确定Web API序列化的方式 反序列化HTTP消息体。有内置的XML支持, JSON和form-urlencoded数据,您可以支持其他媒体 通过编写媒体格式化程序来填写类型。
因此,没有内置的text / plain格式化程序,即:不支持的媒体类型。您可以将内容类型更改为某些支持,内置或实现自定义类型(如link中所述)
答案 1 :(得分:6)
+1 ...根据您的操作,Web API模型绑定会注意到参数fileContents
是一个复杂类型,默认情况下假定使用格式化程序读取请求正文内容。 (请注意,由于fileName
和description
参数属于string
类型,因此默认情况下它们应来自uri。
您可以执行以下操作来阻止模型绑定:
[HttpPost]
[HostAuthentication(DefaultAuthenticationTypes.ExternalBearer)]
[Route("UploadFile")]
public async Task UploadFile(string fileName, string description)
{
byte[] fileContents = await Request.Content.ReadAsByteArrayAsync();
....
}
顺便说一下,你打算用这个fileContents
做什么?你想创建一个本地文件?如果是的话,有更好的方法来解决这个问题。
根据您的上次评论进行更新:
您可以做的快速示例
[HttpPost]
[HostAuthentication(DefaultAuthenticationTypes.ExternalBearer)]
[Route("UploadFile")]
public async Task UploadFile(string fileName, string description)
{
Stream requestStream = await Request.Content.ReadAsStreamAsync();
//TODO: Following are some cases you might need to handle
//1. if there is already a file with the same name in the folder
//2. by default, request content is buffered and so if large files are uploaded
// then the request buffer policy needs to be changed to be non-buffered to imporve memory usage
//3. if exception happens while copying contents to a file
using(FileStream fileStream = File.Create(@"C:\UploadedFiles\" + fileName))
{
await requestStream.CopyToAsync(fileStream);
}
// you need not close the request stream as Web API would take care of it
}