使用Knockout和WebAPI C#实现图片上传

4
我正在尝试使用Knokout JS和web api来上传图片。以下是我的代码:
<div class="row">
<div class="col-sm-4">
    <h3>Send Feedback</h3>
    <form data-bind="submit: sendFeedback">
        <div class="form-group">
            <label>Feedback</label>
            <textarea class="form-control" data-bind="value: feedbackText"></textarea>
        </div>
        <div class="form-group">
            <label>Version Id</label>
            <input class="form-control" type="text" data-bind="value: versionId" />
        </div>
        <div class="form-group">
            <label>Image</label>

            <input class="form-control" type="file"
                   data-bind="file: {data: fileInput, name: fileName, reader: someReader}" />
        </div>
        <div class="form-group">
            <button type="submit" class="btn btn-default">Submit</button>
        </div>
    </form>
</div>

我将使用这个自定义绑定:

https://github.com/TooManyBees/knockoutjs-file-binding

然后在我的脚本代码中,我执行以下操作:

I am using this custom binding

    self.sendFeedback = function () {
    self.result('');

    var feedBackData = {
        versionId: self.versionId(),
        text: self.feedbackText(),
        screenShot: self.fileInput
    };

    $.ajax({
        type: 'POST',
        url: apiUrl + '/Feedback/Add',
        contentType: 'application/json; charset=utf-8',
        data: JSON.stringify(feedBackData)
    }).done(function (data) {
        self.result("Done!");
    }).fail(showError);

}

我对代码的服务器部分不确定。我目前已经写了这部分内容:

    public void Add(HttpPostedFileBase screenShot, String versionId, String text)
    {
        String imgId = null;

        int count = HttpContext.Current.Request.Files.Count;

        if (screenShot != null && screenShot.ContentLength > 0)
        {
            Images img = Images.Create().Save();
            imgId = img.Id;
            BlobHelper.PutFile(imgId, screenShot.InputStream);
        }

        Feedback.Create(versionId, text, imgId).Save(); 

    }

有没有想法如何做到这一点?

你需要使用 ko.toJSON() 而不是 JSON.stringify - observables 是函数,不会被返回。请参考 http://www.knockmeout.net/2011/04/utility-functions-in-knockoutjs.html。 - Quango
我注意到的第二件事是你使用的上传库(knockout-file-binding)将文件数据存储在一个可观察的fileInput中,但是在控制器中你使用了HttpPostedFileBase - 这样混合不同的方法。由于发布的脚本只是部分内容,所以很难添加更多信息。 - Quango
是的,我修复了,但还是不行。我得到的是base64编码字符串的fileInput()。也许这就是问题所在。也许我需要使用其他技术来上传它。 - mohsinali1317
请看我的博客文章,它使用了不同的方法:https://conficient.wordpress.com/2013/07/22/async-file-uploads-with-mvc-webapi-and-bootstrap/ - Quango
哪种方法更好?我能否得到使用HttpPostedFileBase的方法示例? - mohsinali1317
1
已将答案添加为建议 - Quango
1个回答

6
fileInput 包含base64编码的文件数据。它是一个字符串,所以 HttpPostedFileBase 不能使用。
更改表单HTML:
  <input class="form-control" type="file"
               data-bind="file: {data: fileInput}" />

将viewmodel代码更改如下:

// store file data here
self.fileInput = ko.observable(); // is this present already?

var feedBackData = {
        versionId: self.versionId(),
        text: self.feedbackText(),
        screenShot: self.fileInput()
    };

$.ajax({
        type: 'POST',
        url: apiUrl + '/Feedback/Add',
        contentType: 'application/json; charset=utf-8',
        data: ko.toJSON(feedBackData)
    }).done(function (data) {
        self.result("Done!");
    }).fail(showError);

如果控制器方法在API控制器中,它应该接受JSON格式数据,模型绑定器将会提取这些值。
public void Add(String screenShot, String versionId, String text)
    {
        String imgId = null;

        if(!String.IsNullOrEmpty(screenShot))
        {
            Byte[] data = Convert.FromBase64String(screenShot);

        // rest of code omitted

抱歉,我还没有能够对语法等进行测试,但应该可以让您走上正确的轨道。

在开发 Knockout 页面时,一个好的调试提示是使用此行代码,以便您可以查看 viewModel 中正在发生的情况:

<pre data-bind="text: ko.toJSON($data, null, 2)"></pre>

更多帮助请参见http://www.knockmeout.net/2013/06/knockout-debugging-strategies-plugin.html


最好的部分是调试技巧。 - Kaushik Thanki

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接