7

我对 KnockoutJS 很陌生,到目前为止我一直在研究它,但尽我所能,我在任何地方都找不到此信息,所以我希望社区可以提供帮助!在我的视图中,我在文件输入上有以下数据绑定:

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

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

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

self.saveImage = function (MyObject, event) {

    $.post("Service.aspx", MyObject,  function (returnedData) {

    });
}

该对象很好地传递给我的服务,我可以按预期访问所有表单数据,包括“ImageToUpload”变量......但这是我卡住的地方:

1)“ImageToUpload”只是一个字符串,代表我上传的文件的名称,而不是一个字节数组。如何访问图像文件而不仅仅是名称?

2) 有没有更好的方法将 ByteArray 作为 Stream 或响应标头中的其他格式传递?

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

提前致谢!

4

2 回答 2

8

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

于 2012-08-19T09:16:02.740 回答
6

文件上传需要以特殊方式处理。它们通常不属于您的模型。看看下面的 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本质上是通过表单上传的文件的包装器。我必须补充一点, using 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.aspxASP.NET Web API 文件保存为“ BodyPart_3ded2bfb-40be-4183-b789-9301f93e90af"

于 2012-08-19T06:28:20.540 回答