使用MultipartFormDataStreamProvider和ReadAsMultipartAsync

Pet*_*ter 19 c# asp.net asp.net-web-api

我将如何使用MultipartFormDataStreamProviderRequest.Content.ReadAsMultipartAsync使用ApiController

我已经google了一些教程,但我无法让它们中的任何一个工作,我使用.net 4.5.

这就是我目前得到的:

public class TestController : ApiController
{
    const string StoragePath = @"T:\WebApiTest";
    public async void Post()
    {
        if (Request.Content.IsMimeMultipartContent())
        {
            var streamProvider = new MultipartFormDataStreamProvider(Path.Combine(StoragePath, "Upload"));
            await Request.Content.ReadAsMultipartAsync(streamProvider);
            foreach (MultipartFileData fileData in streamProvider.FileData)
            {
                if (string.IsNullOrEmpty(fileData.Headers.ContentDisposition.FileName))
                {
                    throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotAcceptable, "This request is not properly formatted"));
                }
                string fileName = fileData.Headers.ContentDisposition.FileName;
                if (fileName.StartsWith("\"") && fileName.EndsWith("\""))
                {
                    fileName = fileName.Trim('"');
                }
                if (fileName.Contains(@"/") || fileName.Contains(@"\"))
                {
                    fileName = Path.GetFileName(fileName);
                }
                File.Copy(fileData.LocalFileName, Path.Combine(StoragePath, fileName));
            }
        }
        else
        {
            throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotAcceptable, "This request is not properly formatted"));
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我得到了例外

MIME多部分流的意外结束.MIME多部分消息未完成.

await task;运行.有没有人知道我做错了什么或者在使用web api的普通asp.net项目中有一个工作示例.

Pet*_*ter 33

我解决了错误,我不明白这与多部分流的结束有什么关系,但这里是工作代码:

public class TestController : ApiController
{
    const string StoragePath = @"T:\WebApiTest";
    public async Task<HttpResponseMessage> Post()
    {
        if (Request.Content.IsMimeMultipartContent())
        {
            var streamProvider = new MultipartFormDataStreamProvider(Path.Combine(StoragePath, "Upload"));
            await Request.Content.ReadAsMultipartAsync(streamProvider);
            foreach (MultipartFileData fileData in streamProvider.FileData)
            {
                if (string.IsNullOrEmpty(fileData.Headers.ContentDisposition.FileName))
                {
                    return Request.CreateResponse(HttpStatusCode.NotAcceptable, "This request is not properly formatted");
                }
                string fileName = fileData.Headers.ContentDisposition.FileName;
                if (fileName.StartsWith("\"") && fileName.EndsWith("\""))
                {
                    fileName = fileName.Trim('"');
                }
                if (fileName.Contains(@"/") || fileName.Contains(@"\"))
                {
                    fileName = Path.GetFileName(fileName);
                }
                File.Move(fileData.LocalFileName, Path.Combine(StoragePath, fileName));
            }
            return Request.CreateResponse(HttpStatusCode.OK);
        }
        else
        {
            return Request.CreateResponse(HttpStatusCode.NotAcceptable, "This request is not properly formatted");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 我们可以看一个客户端如何调用这个Post方法的例子吗? (2认同)
  • 原始代码的问题是API没有(并且无法)知道`async void`方法何时完成.这就是为什么它设法在你阅读它的途​​中处理流.使用`Task <>`-returning方法,调用代码有机会知道您何时准备好请求,并在您真正不再需要它时关闭流.每当你看到`async void`时,你应该感觉很糟糕. (2认同)

Ham*_*mid 7

首先,您应该在ajax请求标头中将enctype定义为multipart/form-data.

[Route("{bulkRequestId:int:min(1)}/Permissions")]
    [ResponseType(typeof(IEnumerable<Pair>))]
    public async Task<IHttpActionResult> PutCertificatesAsync(int bulkRequestId)
    {
        if (Request.Content.IsMimeMultipartContent("form-data"))
        {
            string uploadPath = HttpContext.Current.Server.MapPath("~/uploads");

            var streamProvider = new MyStreamProvider(uploadPath);

            await Request.Content.ReadAsMultipartAsync(streamProvider);

            List<Pair> messages = new List<Pair>();
            foreach (var file in streamProvider.FileData)
            {
                FileInfo fi = new FileInfo(file.LocalFileName);
                messages.Add(new Pair(fi.FullName, Guid.NewGuid()));
            }

            //if (_biz.SetCertificates(bulkRequestId, fileNames))
            //{
            return Ok(messages);
            //}
            //return NotFound();
        }
        return BadRequest();
    }
}




public class MyStreamProvider : MultipartFormDataStreamProvider
{
    public MyStreamProvider(string uploadPath) : base(uploadPath)
    {
    }
    public override string GetLocalFileName(HttpContentHeaders headers)
    {
        string fileName = Guid.NewGuid().ToString()
            + Path.GetExtension(headers.ContentDisposition.FileName.Replace("\"", string.Empty));
        return fileName;
    }
}
Run Code Online (Sandbox Code Playgroud)