在同一个web api 2端点发送原始JSON和文件

时间:2016-09-07 13:06:07

标签: c# angularjs json asp.net-web-api

我想知道是否可以发送文件(我只想要“.pdf”,“.jpg”或“.png”)以及原始JSON。 到目前为止,我的所有端点都发送原始JSON(我正在通过Postman进行测试,因为前端尚不存在),目的是使用Angular Js发送表单数据。我还不知道Angular Js,所以我无法想象它是如何工作的。

有问题的端点的签名如下所示:

[Route("Post")]
    [CustomAuthorize(Roles = "User, Admin")]
    [ValidateJWT]
    public async Task<IHttpActionResult> Post(HttpRequestMessage request, SalesOrderViewModel orderData)

视图模型只是一个c#类,其中包含模型绑定器从JSON转换的字符串属性。

我想知道是否可以在使用Web API 2的同一端点中发送原始JSON和用户将选择的文件。 是吗?

提前致谢。

2 个答案:

答案 0 :(得分:1)

您不能使用post作为aplication / json进行指导,仍然可以使用多个表单字段(作为表单数据),文件+数据,其中数据的值可以是JSON。

我不推荐这种方法,但是要做到这一点:

public async Task<IHttpActionResult> Post()
        {
            if (!Request.Content.IsMimeMultipartContent())
            {
                Request.CreateResponse(HttpStatusCode.UnsupportedMediaType);
            }

            //load in a memory stream or in azure blob storage
            var uploadFolder = "~/App_Data/FileUploads"; // to demonstrate the upload so please don't comment about where I'm saving the file, don't recommend this under no circumstance
            var root = HttpContext.Current.Server.MapPath(uploadFolder);
            Directory.CreateDirectory(root);
            var provider =  new MultipartFormDataStreamProvider(root);
            var result = await Request.Content.ReadAsMultipartAsync(provider);

            if (result.FileData.FirstOrDefault() == null)
            {
                return BadRequest("No import file was attached");
            }

            var uploadedFileInfo = new FileInfo(result.FileData.First().LocalFileName);

            var model = result.FormData["model"];

            if (model == null)
            {
                return BadRequest("Model is missing");
            }

            var parameters = JsonConvert.DeserializeObject<Coords>(model);

            var byteArray = File.ReadAllBytes(uploadedFileInfo.FullName);
           //..process the bytes
           //..process json passed in headers
}

模特:

public class Coords
    {
        public Cord[] cords { get; set; }
    }

    public class Cord
    {
        public int x { get; set; }
        public object y { get; set; }
    }

邮递员电话:

enter image description here

答案 1 :(得分:1)

修改:刚查过,您不必使用IEnumerable<byte>。使用byte[]可以正常工作。

WebApi支持将JSON数组反序列化为IEnumerable<T>,以便您可以通过IEnumerable<byte>声明来接收字节。

以下示例将说明如何上传图片:

public class ImageModel
{
    public string Name { get; set; }
    public IEnumerable<byte> Bytes { get; set; }
}

在你的控制器中。将图像写入磁盘:

private string WriteImage(byte[] arr)
{
    var filename = $@"images\{DateTime.Now.Ticks}.";

    using (var im = Image.FromStream(new MemoryStream(arr)))
    {
        ImageFormat frmt;
        if (ImageFormat.Png.Equals(im.RawFormat))
        {
            filename += "png";
            frmt = ImageFormat.Png;
        }
        else
        {
            filename += "jpg";
            frmt = ImageFormat.Jpeg;
        }
        string path = HttpContext.Current.Server.MapPath("~/") + filename;
        im.Save(path, frmt);
    }

    return $@"http:\\{Request.RequestUri.Host}\{filename}";
}

HttpContext.Current.Server.MapPath("~/")将提供服务器运行的内部路径。 Request.RequestUri.Host返回主机名。

public IHttpActionResult UploadImage(ImageModel model)
{
    var imgUrl = WriteImage(model.Bytes.ToArray());

    // Some code
}

在HTML中:

<input type="file" id="imageFile"/>

AngularJS的上传方法:

$scope.upload = function () {

     var file = document.getElementById("imageFile").files[0];
     var r = new FileReader();
     r.onloadend = function (e) {


         var arr = Array.from(new Uint8Array(e.target.result));

         var uploadData = {
             Name: "Name of Image",
             Bytes: arr
         }
         console.log(uploadData);

         $http.post('api/Uploader/UploadImage', uploadData)
         .then(
         function (response) {
             console.log(response);
         },

         function (reason) {

             console.log(reason);
         })
     }
     r.readAsArrayBuffer(file);
 }