最近开发一个新项目,使用了asp.net core 2.0,采用webapi开发后台,postgresql为数据库。最早来的问题就是上传文件的问题。html
使用默认模板建立webapi的controller后,post请求,默认有前端
// POST api/values [HttpPost] public void Post([FromBody]string value) { }
请求使用了[FromBody]
标记,用来指示用请求体里得到数据。web
对于文件上传请求,直接在这个Post函数里使用Request.Form.Files
是不行的,没法成功路由。
典型上传,须要设置前端发送的请求Content-Type
为multipart/form-data
,而后在控制器类加上特性修饰:sql
[Produces("application/json")] [Consumes("application/json", "multipart/form-data")]//此处为新增 [Route("api/[controller]")] public class FileController : Controller
指示该controller可以接受multipart/form-data
形式的数据。对应的,修改post的代码以下:数据库
// POST: api/File [HttpPost] public Task<ActionResult> Post(IFormCollection files)
这里须要注意,使用的是IFormCollection。这是IForm的类型集合,实际上就是Request.Form
。json
注意,不少地方写了可使用IFormFile,直接写成c#
// POST: api/File [HttpPost] public Task<ActionResult> Post(IFormFile file)
实际测试没有办法获取到对象,file常态为null,或者是我方法不对。api
而后就能够在post方法里面使用files.Files来枚举文件了,每一个文件都是一个IFormFile对象,能够灵活使用FileName, Name,Length等经常使用属性。固然,咱们也能够不带参数:app
// POST: api/File [HttpPost] public Task<ActionResult> Post()
直接使用Request.Form.Files得到文件数据。asp.net
P.S. 对于IFormFile,与
System.IO.File
对象不一样,IFormFile缺乏不少方法,只提供OpenReadStream()
方法,该方法返回一个stream对象。不少读文件的API均可以接受stream做为FilePath的替代。
通常的文件上传请求,不单上传文件数据,一般还须要上传其余文件信息数据(好比文件类型,上传者等等)。修改一下post方法,改为这样:
[HttpPost] public Task<ActionResult> Post([FromBody]string type,IFormCollection files)
将type都打包进请求,再次发送。发现......type是null。
MSDN说了,The reason for this rule is that the request body might be stored in a non-buffered stream that can only be read once.
因此,[FromBody]只能加一个,可是我这确实也只加了一个,有问题?很明显,那个IFormCollection也是默认经过[FromBody]解析的,因此正确的方法是不加[FromBody]了。
[HttpPost] public Task<ActionResult> Post(string type,IFormCollection files)
回想起当年作WebService的时候,上传文件写的
多平台上传
,感触颇多,之前是转码到base64,经过string发送,如今是直接类型识别...
BUT
他喵的还在传文件啊,原地踏步啊,三年了难受!