将ByteArray从Knockout.js发布到Web服务

Posting ByteArray from Knockout.js to a Web Service

本文关键字:Web 服务 js ByteArray Knockout      更新时间:2023-09-26

我是KnockoutJS的新手,到目前为止我很了解它,但尽管我尽了最大努力,我在任何地方都找不到这些信息,所以我希望社区能提供帮助!在我看来,我在文件输入上有以下数据绑定:

 <input type="file" data-bind="value: ImageToUpload"/>
 <button data-bind="click: $root.saveImage">Upload</button>

这是"foreach"div中列表的一部分,因此变量"ImageToUpload"对应于该列表中对象的属性。

在我的ViewModel中,Upload按钮调用saveImage(),我调用web服务并将表单数据传递到.aspx页面:

self.saveImage = function (MyObject, event) {
    $.post("Service.aspx", MyObject,  function (returnedData) {
    });
}

对象很好地传递到我的服务,我可以访问所有预期的表单数据,包括"ImageToUpload"变量。。。但这是我被卡住的地方:

1) "ImageToUpload"只是代表我上传的文件名称的字符串,而不是ByteArray。如何访问图像文件而不仅仅是名称?

2) 有没有更好的方法在响应标头中以流或其他格式传递ByteArray?

3) 我的技术完全失灵了吗?有更好的方法吗?我的目标是有一个动态列表的图像"插槽"上传到。

提前感谢!

无法访问本地文件内容是JavaScript安全沙箱的一个基本限制。随着HTML5文件API的引入,它被提升了,但不幸的是,支持还远远没有普及。如果你的代码需要在不兼容的浏览器中工作,你唯一的选择就是让浏览器处理传统的multipart/form-data上传。另一方面,如果不支持IE<10对您来说很好,可以使用带有自定义绑定的文件API"淘汰方式"。看看这个例子:http://khayrov.github.com/jsfiddle/knockout-fileapi(由于某种原因,当我尝试在jsFiddle中运行此代码时,它对我来说非常糟糕)。Github上的源代码。

文件上传需要以特殊方式处理。它们通常不属于您的模型。看看下面的ApiController。诸如MultipartFormDataStreamProvider之类的专用类用于访问提交给控制器的二进制数据。

public class FileUploadController : ApiController
{
    [HttpPost]
    public List<FileResult> UploadFile()
    {
        // Verify that this is an HTML Form file upload request
        if (!Request.Content.IsMimeMultipartContent("form-data"))
        {
            throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
        }
        // Create a stream provider for setting up output streams
        MultipartFormDataStreamProvider streamProvider = new MultipartFormDataStreamProvider();
        // Read the MIME multipart content using the stream provider we just created.
        IEnumerable<HttpContent> bodyparts = Request.Content.ReadAsMultipartAsync(streamProvider).Result;
        // The submitter field is the entity with a Content-Disposition header field with a "name" parameter with value "submitter"
        string submitter;
        if (!bodyparts.TryGetFormFieldValue("submitter", out submitter))
        {
            submitter = "unknown";
        }
        // Get a dictionary of local file names from stream provider.
        // The filename parameters provided in Content-Disposition header fields are the keys.
        // The local file names where the files are stored are the values.
        IDictionary<string, string> bodyPartFileNames = streamProvider.BodyPartFileNames;
        // Create response containing information about the stored files.
        return bodyPartFileNames.Select(kv =>
        {
            FileInfo fileinfo = new FileInfo(kv.Value);
            return new FileResult
            {
                FileName = kv.Key,
                LocalPath = fileinfo.FullName,
                LastModifiedTime = fileinfo.LastWriteTimeUtc,
                Length = fileinfo.Length,
                Submitter = submitter
            };
        }).ToList();
    }
    private static bool TryGetFormFieldValue(IEnumerable<HttpContent> contents, string dispositionName, out string formFieldValue)
    {
        HttpContent content = contents.FirstDispositionNameOrDefault(dispositionName);
        if (content != null)
        {
            formFieldValue = content.ReadAsStringAsync().Result;
            return true;
        }
        formFieldValue = null;
        return false;
    }
}

另一种对代码不那么重的解决方案是使用HttpPostedFileBase作为ApiController的参数。HttpPostedFileBase本质上是通过表单上传的文件的包装器。我必须补充一点,使用MultipartFormDataStreamProvider比使用HttpPostedFileBase更可取,因为后者是ASP.NET MVC框架的一部分。请记住,WebAPI技术可以在ASP.NET MVC之外使用。

更多信息:http://blogs.msdn.com/b/henrikn/archive/2012/03/01/file-upload-and-asp-net-web-api.aspx以及保存为"的ASP.NET Web API文件;BodyPart_3ded2bfb-40be-4183-b789-9301f93e90af";