骨干。表单带有文件上传,如何处理?

发布于 2024-12-16 13:55:41 字数 129 浏览 0 评论 0原文

我只想通过 REST API 组织工作流程。我有一个允许上传图像的表单(enctype="multipart/form-data")。我如何通过主干处理此表单?请帮助我,如何使用文件字段将其序列化为 JSON。

谢谢。 维塔利

I want to organize the workflow only through the REST API. I have a form that allows to upload image (enctype="multipart/form-data"). How do I handle this form via backbone? Help me please, how I can to serialize it into JSON with a file field.

Thanks.
Vitaliy

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

风和你 2024-12-23 13:55:41

如果您使用的是 HTML5,则可以使用文件 api 中的 readAsDataURL 方法来读取它并将其存储在模型上。

这是我用来读取和存储的代码。

var Image = Backbone.Model.extend({

    readFile: function(file) {
        var reader = new FileReader();
        // closure to capture the file information.
        reader.onload = (function(theFile,that) {
            return function(e) {
                //set model
                that.set({filename: theFile.name, data: e.target.result});

            };
        })(file,this);

        // Read in the image file as a data URL.
        reader.readAsDataURL(file);
    }   
});

If you are using HTML5, you can use the readAsDataURL method from the file api to read and store it on your models.

Here's the code i use to read and store.

var Image = Backbone.Model.extend({

    readFile: function(file) {
        var reader = new FileReader();
        // closure to capture the file information.
        reader.onload = (function(theFile,that) {
            return function(e) {
                //set model
                that.set({filename: theFile.name, data: e.target.result});

            };
        })(file,this);

        // Read in the image file as a data URL.
        reader.readAsDataURL(file);
    }   
});
假扮的天使 2024-12-23 13:55:41

您可以尝试 jquery.iframe.transport 插件。

You could try the jquery.iframe.transport plugin.

心如狂蝶 2024-12-23 13:55:41

恕我直言,您无法将文件序列化为 JSON。
如果您需要随文件一起发送一些数据,您可以使用 POST 方法将它们作为查询参数发送。

www.example.com/upload?param1=value1¶m2=value2

IMHO, you cannot serialize a file into JSON.
If you need to send some data along with the file you can send them as query params with POST method.

www.example.com/upload?param1=value1¶m2=value2
独﹏钓一江月 2024-12-23 13:55:41

没有通过 AJAX 提交文件的好方法。所以我写了一个函数来伪造它——它将一个秘密 iframe 插入到你的 DOM 中,该 iframe 永远不可见,但仍然可以作为提交表单的目标,并且它会安装一个函数供你的响应调用,当文件已上传。

让您的上传表单的提交按钮触发我编写的这个函数。它使用 jQuery,因为它简单又漂亮,但原则上这不是绝对必要的:

function backgroundUpload(form, container) {
    $(container).append('<iframe name="targetFrame" id="targetFrame" style="display: none; height: 0px; width:0px;" ></iframe>');
    $(form).attr('target', 'targetFrame');

    window.backgroundUploadComplete = function() {
        //clear your form:
        $(form).find(':file').val('');
        $(form).find(':text').val('');

        //do whatever you do to reload your screenful of data (I'm in Backbone.js, so:)
        window.Docs.fetch().complete( function() { populateDocs(); });

        //get rid of the target iframe
        $('#targetFrame').remove();
    };
    $(form).submit();
}

然后让您的表单处理程序执行文件解析并保存返回字符串:

<script>window.parent.backgroundUploadComplete();</script>

您的表单可以如下所示:

<form id="uploadForm" method="POST" action="/your/form/processor/url" enctype="multipart/form-data">
<input type="file" name="file"/>
<!-- and other fields as needed -->
<input type="button" onClick="backgroundUpload(this.form, $('#documents'));" value="Upload" />
</form>

(#documents 是这个 div form 存在于其中。可能是任何 DOM 元素,它只需要一个家。)

There's no good way to submit a file via AJAX. So I wrote a function to fake it--it inserts a secret iframe into your DOM that is never visible but still works as a target to submit your form on, and it installs a function for your response to call that cleans house when the file is uploaded.

Have your upload form's submit button fire this function I wrote. It uses jQuery because it's easy and nice, but in principle that shouldn't be strictly necessary:

function backgroundUpload(form, container) {
    $(container).append('<iframe name="targetFrame" id="targetFrame" style="display: none; height: 0px; width:0px;" ></iframe>');
    $(form).attr('target', 'targetFrame');

    window.backgroundUploadComplete = function() {
        //clear your form:
        $(form).find(':file').val('');
        $(form).find(':text').val('');

        //do whatever you do to reload your screenful of data (I'm in Backbone.js, so:)
        window.Docs.fetch().complete( function() { populateDocs(); });

        //get rid of the target iframe
        $('#targetFrame').remove();
    };
    $(form).submit();
}

Then have your form handler that does your file parsing and saving return the string:

<script>window.parent.backgroundUploadComplete();</script>

Your form can look like:

<form id="uploadForm" method="POST" action="/your/form/processor/url" enctype="multipart/form-data">
<input type="file" name="file"/>
<!-- and other fields as needed -->
<input type="button" onClick="backgroundUpload(this.form, $('#documents'));" value="Upload" />
</form>

(#documents is the div that this form lives in. Could probably be any DOM element, it just needs a home.)

猥︴琐丶欲为 2024-12-23 13:55:41
events : {
        "click #uploadDocument" : "showUploadDocumentDetails",
        "change #documents" : "documentsSelected",
        "click .cancel-document" : "cancelDocument"
    },
    showUploadDocumentDetails : function(event) {
        $('#id-gen-form').attr("enctype","multipart/form-data");
        $('#id-gen-form').attr("action",this.model.url);
        var config = {
                support : "image/jpg,image/png,image/bmp,image/jpeg,image/gif",     // Valid file formats
                form: "id-gen-form",                    // Form ID
                dragArea: "dragAndDropFiles",       // Upload Area ID
                uploadUrl: this.model.url               // Server side upload url
            };

                initMultiUploader(config);




        if($('#uploadDocument').attr("checked")){
            $('#id-documentCategory-div').show();
            $('#id-documentName-div').show();
            this.model.set({"uploadDocument": "YES"},{silent: true});
        }
        else{
            $('#id-documentCategory-div').hide();
            $('#id-documentName-div').hide();
            this.model.set({"uploadDocument": "NO"},{silent: true});
        }
    },
    cancelDocument : function(event) {
        var targ;
        if (!event) event = window.event;
        if (event.target) targ = event.target;
        else if (event.srcElement) targ = event.srcElement;
         $('#' + event.target.id).parent().parent().remove();
         var documentDetails = this.model.get("documentDetails");
         documentDetails = _.without(documentDetails, _(documentDetails).find(function(x) {return x.seqNum == event.target.id;}));
         this.model.set({
                "documentDetails" : documentDetails
            }, {
                silent : true
            });
    },
    documentsSelected : function(event) {
        /*var targ;
        if (!event) event = window.event;
        if (event.target) targ = event.target;
        else if (event.srcElement) targ = event.srcElement;
        if (targ.nodeType == 3) // defeat Safari bug
        targ = targ.parentNode;
                var files = event.target.files; // FileList object

                var html = [];
                var documentDetails = [];
                $(".files").html(html.join(''));
                var _this = this;
                _this.model.set({
                    "documentDetails" : documentDetails
                }, {
                    silent : true
                });
                 var seqNum = 0;
            for(var i=0; i< files.length; i++){

                (function(file) {
                    html.push("<tr class='template-upload' style='font-size: 10px;'>");
                    html.push("<td class='name'><span>"+file.name+"</span></td>");
                    html.push("<td class='size'><span>"+file.size+" KB <br/>"+file.type+"</span></td>");
                    //html.push("<td><div class='progress progress-success progress-striped active'style='width: 100px;' role='progressbar' aria-valuemin='0' aria-valuemax='100' aria-valuenow='0'><div class='bar' style='width:0%;'></div></div></td>");
                    if(LNS.MyesqNG.isMimeTypeSupported(file.type)){
                        if(!LNS.MyesqNG.isFileSizeExceeded(file.size)){
                            html.push("<td class='error' colspan='2'></td>");
                            var reader = new FileReader();  
                            console.log(reader);
                                reader.onload = function(e) { 
                                      var targ;
                                    if (!e) e = window.event;
                                    if (e.target) targ = e.target;
                                    else if (e.srcElement) targ = e.srcElement;
                                    if (targ.nodeType == 3) // defeat Safari bug
                                    targ = targ.parentNode;
                                    console.log(e.target.result);
                                      var content = e.target.result;
                                      var document = new Object();
                                      document.name = file.name;
                                      document.type = file.type;
                                      document.content = content;
                                      document.seqNum = "document"+seqNum;
                                      seqNum++;
                                      documentDetails.push(document);
                                     // _this.model.set({"documentDetails" : documentDetails},{silent:true});
                                  };
                                reader.readAsDataURL(file, "UTF-8");
                        }else{
                             seqNum++;
                            html.push("<td class='error' colspan='2'><span class='label label-important'>Error</span> Too long</td>");
                        }
                }else{
                     seqNum++;
                    html.push("<td class='error' colspan='2'><span class='label label-important'>Error</span> Not suported</td>");
                }
                 html.push("<td><a id='document"+i+"' class='btn btn-warning btn-mini cancel-document'>Cancel</a></td>");
                 html.push("</tr>");
                })(files[i]);
            }
            $(".files").html(html.join(''));*/

      }


LNS.MyesqNG.isMimeTypeSupported = function(mimeType){
    var mimeTypes = ['text/plain','application/zip','application/x-rar-compressed','application/pdf'];
    if($.inArray(mimeType.toLowerCase(), mimeTypes) == -1) {
        return false;
    }else{
        return true;
    }
};

LNS.MyesqNG.isFileSizeExceeded = function(fileSize) {
    var size = 2000000000000000000000000000;
    if(Number(fileSize) > Number(size)){
        return true;
    }else{
        return false;
    }
};


Use this, it can work but not more than 5 MB file
events : {
        "click #uploadDocument" : "showUploadDocumentDetails",
        "change #documents" : "documentsSelected",
        "click .cancel-document" : "cancelDocument"
    },
    showUploadDocumentDetails : function(event) {
        $('#id-gen-form').attr("enctype","multipart/form-data");
        $('#id-gen-form').attr("action",this.model.url);
        var config = {
                support : "image/jpg,image/png,image/bmp,image/jpeg,image/gif",     // Valid file formats
                form: "id-gen-form",                    // Form ID
                dragArea: "dragAndDropFiles",       // Upload Area ID
                uploadUrl: this.model.url               // Server side upload url
            };

                initMultiUploader(config);




        if($('#uploadDocument').attr("checked")){
            $('#id-documentCategory-div').show();
            $('#id-documentName-div').show();
            this.model.set({"uploadDocument": "YES"},{silent: true});
        }
        else{
            $('#id-documentCategory-div').hide();
            $('#id-documentName-div').hide();
            this.model.set({"uploadDocument": "NO"},{silent: true});
        }
    },
    cancelDocument : function(event) {
        var targ;
        if (!event) event = window.event;
        if (event.target) targ = event.target;
        else if (event.srcElement) targ = event.srcElement;
         $('#' + event.target.id).parent().parent().remove();
         var documentDetails = this.model.get("documentDetails");
         documentDetails = _.without(documentDetails, _(documentDetails).find(function(x) {return x.seqNum == event.target.id;}));
         this.model.set({
                "documentDetails" : documentDetails
            }, {
                silent : true
            });
    },
    documentsSelected : function(event) {
        /*var targ;
        if (!event) event = window.event;
        if (event.target) targ = event.target;
        else if (event.srcElement) targ = event.srcElement;
        if (targ.nodeType == 3) // defeat Safari bug
        targ = targ.parentNode;
                var files = event.target.files; // FileList object

                var html = [];
                var documentDetails = [];
                $(".files").html(html.join(''));
                var _this = this;
                _this.model.set({
                    "documentDetails" : documentDetails
                }, {
                    silent : true
                });
                 var seqNum = 0;
            for(var i=0; i< files.length; i++){

                (function(file) {
                    html.push("<tr class='template-upload' style='font-size: 10px;'>");
                    html.push("<td class='name'><span>"+file.name+"</span></td>");
                    html.push("<td class='size'><span>"+file.size+" KB <br/>"+file.type+"</span></td>");
                    //html.push("<td><div class='progress progress-success progress-striped active'style='width: 100px;' role='progressbar' aria-valuemin='0' aria-valuemax='100' aria-valuenow='0'><div class='bar' style='width:0%;'></div></div></td>");
                    if(LNS.MyesqNG.isMimeTypeSupported(file.type)){
                        if(!LNS.MyesqNG.isFileSizeExceeded(file.size)){
                            html.push("<td class='error' colspan='2'></td>");
                            var reader = new FileReader();  
                            console.log(reader);
                                reader.onload = function(e) { 
                                      var targ;
                                    if (!e) e = window.event;
                                    if (e.target) targ = e.target;
                                    else if (e.srcElement) targ = e.srcElement;
                                    if (targ.nodeType == 3) // defeat Safari bug
                                    targ = targ.parentNode;
                                    console.log(e.target.result);
                                      var content = e.target.result;
                                      var document = new Object();
                                      document.name = file.name;
                                      document.type = file.type;
                                      document.content = content;
                                      document.seqNum = "document"+seqNum;
                                      seqNum++;
                                      documentDetails.push(document);
                                     // _this.model.set({"documentDetails" : documentDetails},{silent:true});
                                  };
                                reader.readAsDataURL(file, "UTF-8");
                        }else{
                             seqNum++;
                            html.push("<td class='error' colspan='2'><span class='label label-important'>Error</span> Too long</td>");
                        }
                }else{
                     seqNum++;
                    html.push("<td class='error' colspan='2'><span class='label label-important'>Error</span> Not suported</td>");
                }
                 html.push("<td><a id='document"+i+"' class='btn btn-warning btn-mini cancel-document'>Cancel</a></td>");
                 html.push("</tr>");
                })(files[i]);
            }
            $(".files").html(html.join(''));*/

      }


LNS.MyesqNG.isMimeTypeSupported = function(mimeType){
    var mimeTypes = ['text/plain','application/zip','application/x-rar-compressed','application/pdf'];
    if($.inArray(mimeType.toLowerCase(), mimeTypes) == -1) {
        return false;
    }else{
        return true;
    }
};

LNS.MyesqNG.isFileSizeExceeded = function(fileSize) {
    var size = 2000000000000000000000000000;
    if(Number(fileSize) > Number(size)){
        return true;
    }else{
        return false;
    }
};


Use this, it can work but not more than 5 MB file
岁月流歌 2024-12-23 13:55:41

根据安东尼的回答(https://stackoverflow.com/a/10916733/2750451),我编写了一个解决方案在基于 defer 对象的 CoffeeScript 中。

 readFile: (file) =>
   def = $.Deferred()
   reader = new FileReader()

   reader.onload = (ev) =>
     def.resolve
       name: file.name
       binary: ev.target.result

   reader.onerror = ->
     def.reject()

   reader.readAsDataURL(file)
   def.promise()

然后,您可以这样使用它

     readFile(file)
       .done (parsedFile) =>
         # do whatever you want with parsedFile
         @model.set
           image_name: parsedFile.name
           image: parsedFile.binary
         @model.save
       .fail ->
         console.log "readFile has failed"

在服务器端处理它(因为它是Base64编码的),这里是RoR中的解决方案(基于 https://stackoverflow.com/a/16310953/2750451

 my_object.image =      decode_image(params[:image])
 my_object.image.name = params[:image_name]

 def decode_image(encoded_file)
   require 'base64'
   image_data_string = split_base64(encoded_file)[:data]
   Base64.decode64(image_data_string)
 end

 def split_base64(uri)
   if uri.match(%r{^data:(.*?);(.*?),(.*)$})
     return {
       type:      $1, # "image/png"
       encoder:   $2, # "base64"
       data:      $3, # data string
       extension: $1.split('/')[1] # "png"
       }
   end
 end

Based on Anthony answer (https://stackoverflow.com/a/10916733/2750451), I've written a solution in coffeescript based on a defer object.

 readFile: (file) =>
   def = $.Deferred()
   reader = new FileReader()

   reader.onload = (ev) =>
     def.resolve
       name: file.name
       binary: ev.target.result

   reader.onerror = ->
     def.reject()

   reader.readAsDataURL(file)
   def.promise()

Then, you could use it this way

     readFile(file)
       .done (parsedFile) =>
         # do whatever you want with parsedFile
         @model.set
           image_name: parsedFile.name
           image: parsedFile.binary
         @model.save
       .fail ->
         console.log "readFile has failed"

To handle it on the server side (because it's Base64 encoded), here the solution in RoR (based on https://stackoverflow.com/a/16310953/2750451)

 my_object.image =      decode_image(params[:image])
 my_object.image.name = params[:image_name]

 def decode_image(encoded_file)
   require 'base64'
   image_data_string = split_base64(encoded_file)[:data]
   Base64.decode64(image_data_string)
 end

 def split_base64(uri)
   if uri.match(%r{^data:(.*?);(.*?),(.*)$})
     return {
       type:      $1, # "image/png"
       encoder:   $2, # "base64"
       data:      $3, # data string
       extension: $1.split('/')[1] # "png"
       }
   end
 end
夜无邪 2024-12-23 13:55:41

详细阐述蔡美儿的回答。您需要将图像处理添加到 Backbone.Form.editors 中,例如

Backbone.Form.editors.Image = Backbone.Form.editors.Text.extend({
    tagName: 'div',

    events: {
        'change input[type=file]': 'uploadFile',
        'click .remove': 'removeFile'
    },

    initialize: function(options) {
        _.bindAll(this, 'filepickerSuccess', 'filepickerError', 'filepickerProgress');
        Backbone.Form.editors.Text.prototype.initialize.call(this, options);
        this.$input = $('<input type="hidden" name="'+this.key+'" />');
        this.$uploadInput = $('<input type="file" name="'+this.key+'" accept="image/*" />');
        this.$loader = $('<p class="upload-status"><span class="loader"></span> please wait..</p>');
        this.$error = $('<p class="upload-error error">Error</p>');
        this.$list = $('<ul class="file-list">');
    },

    // return an array of file dicts
    getValue: function() {
        var val = this.$input.val();
        return (val ? JSON.parse(val) : [])[0].value;
    },

    setValue: function(value) {
        var str, files = value;
        if (_(value).isObject()) {
            str = JSON.stringify(value);
        } else {
            files = value ? JSON.parse(value) : [];
        }
        this.$input.val(str);
        this.updateList(files);
    },

    render: function(options) {
        Backbone.Form.editors.Text.prototype.render.apply(this, arguments);

        this.$el.append(this.$input);
        this.$el.append(this.$uploadInput);
        this.$el.append(this.$loader.hide());
        this.$el.append(this.$error.hide());
        this.$el.append(this.$list);
        return this;
    },

    uploadFile: function() {
        var fileInput = this.$uploadInput.get(0);
        var fileObj = fileInput.files[0]
        var reader = new FileReader();
        var that = this;
        // closure to capture the file information.
        reader.onload = function(file){
            var dataURL = reader.result;
            var fileValue = {
                value: dataURL,
                name: fileObj.name,
                content_type: fileObj.type
            }
            that.filepickerSuccess(fileValue);
        };

        // Read in the image file as a data URL.
        reader.readAsDataURL(fileObj);
    },

    filepickerSuccess: function(files) {
        console.log('File (raw)', files);
        this.$loader.hide();
        this.$error.hide();
        this.$uploadInput.val('');

        // when uploading one file, it returns just an object
        if (!_(files).isArray()) { files = [files]; }

        // turn response array into a flatter array of objects
        var newFiles = _(files).map(function(file, index) {
            return {
                url: "#",
                value: file.value,
                filename: file.name,
                key: index,
                content_type: file.type
            };
        });
        console.log('File (processed)', newFiles);
        this.setValue(newFiles);
    },

    filepickerError: function(msg) {
        console.debug('File error', msg);
        this.$loader.hide();
        this.$error.show();
    },

    filepickerProgress: function(percent) {
        this.$loader.show();
        this.$error.hide();
    },

    updateList: function(files) {
        // this code is currently duplicated as a handlebar helper (I wanted to let this
        // backbone-forms field stand on its own)

        this.$list.empty();
        _(files).each(function(file) {
            var a = $('<a>', {
                target: '_blank',
                href: file.url,
                text: file.filename + ' (' + file.content_type + ') '
            });
            var li = $('<li>').append(a);
            li.append(a, ' ', $('<a href="#" class="remove"><i class="icon-remove"></i></a>').data('key', file.key));
            this.$list.append(li);
        }, this);

        this.$list[files.length ? 'show' : 'hide']();
    },

    removeFile: function(ev) {
        if (ev) ev.preventDefault();
        var files = this.getValue();
        this.setValue([]);
    }

});

您可以使用上面的代码,如下所示

var ImgSlot = Backbone.Model.extend({
  defaults: {
  },
  schema: {
    imageField: {
      type: "Image"
    }
  }
})

渲染表单:

this.form = new Backbone.Form({
  model: new ImgSlot(),
  submitButton: "Example Image file input handling"
}).render();

var errors = that.form.commit({validate: true})
if(errors != null)
  {
    return false;
  }
var data = that.form.model.attributes;
console.debug(data.imageField); // Will return base64 of image selected.

To ellaborate on Anthony Chua's answer. You need to add Image handling to Backbone.Form.editors like

Backbone.Form.editors.Image = Backbone.Form.editors.Text.extend({
    tagName: 'div',

    events: {
        'change input[type=file]': 'uploadFile',
        'click .remove': 'removeFile'
    },

    initialize: function(options) {
        _.bindAll(this, 'filepickerSuccess', 'filepickerError', 'filepickerProgress');
        Backbone.Form.editors.Text.prototype.initialize.call(this, options);
        this.$input = $('<input type="hidden" name="'+this.key+'" />');
        this.$uploadInput = $('<input type="file" name="'+this.key+'" accept="image/*" />');
        this.$loader = $('<p class="upload-status"><span class="loader"></span> please wait..</p>');
        this.$error = $('<p class="upload-error error">Error</p>');
        this.$list = $('<ul class="file-list">');
    },

    // return an array of file dicts
    getValue: function() {
        var val = this.$input.val();
        return (val ? JSON.parse(val) : [])[0].value;
    },

    setValue: function(value) {
        var str, files = value;
        if (_(value).isObject()) {
            str = JSON.stringify(value);
        } else {
            files = value ? JSON.parse(value) : [];
        }
        this.$input.val(str);
        this.updateList(files);
    },

    render: function(options) {
        Backbone.Form.editors.Text.prototype.render.apply(this, arguments);

        this.$el.append(this.$input);
        this.$el.append(this.$uploadInput);
        this.$el.append(this.$loader.hide());
        this.$el.append(this.$error.hide());
        this.$el.append(this.$list);
        return this;
    },

    uploadFile: function() {
        var fileInput = this.$uploadInput.get(0);
        var fileObj = fileInput.files[0]
        var reader = new FileReader();
        var that = this;
        // closure to capture the file information.
        reader.onload = function(file){
            var dataURL = reader.result;
            var fileValue = {
                value: dataURL,
                name: fileObj.name,
                content_type: fileObj.type
            }
            that.filepickerSuccess(fileValue);
        };

        // Read in the image file as a data URL.
        reader.readAsDataURL(fileObj);
    },

    filepickerSuccess: function(files) {
        console.log('File (raw)', files);
        this.$loader.hide();
        this.$error.hide();
        this.$uploadInput.val('');

        // when uploading one file, it returns just an object
        if (!_(files).isArray()) { files = [files]; }

        // turn response array into a flatter array of objects
        var newFiles = _(files).map(function(file, index) {
            return {
                url: "#",
                value: file.value,
                filename: file.name,
                key: index,
                content_type: file.type
            };
        });
        console.log('File (processed)', newFiles);
        this.setValue(newFiles);
    },

    filepickerError: function(msg) {
        console.debug('File error', msg);
        this.$loader.hide();
        this.$error.show();
    },

    filepickerProgress: function(percent) {
        this.$loader.show();
        this.$error.hide();
    },

    updateList: function(files) {
        // this code is currently duplicated as a handlebar helper (I wanted to let this
        // backbone-forms field stand on its own)

        this.$list.empty();
        _(files).each(function(file) {
            var a = $('<a>', {
                target: '_blank',
                href: file.url,
                text: file.filename + ' (' + file.content_type + ') '
            });
            var li = $('<li>').append(a);
            li.append(a, ' ', $('<a href="#" class="remove"><i class="icon-remove"></i></a>').data('key', file.key));
            this.$list.append(li);
        }, this);

        this.$list[files.length ? 'show' : 'hide']();
    },

    removeFile: function(ev) {
        if (ev) ev.preventDefault();
        var files = this.getValue();
        this.setValue([]);
    }

});

You can use above code as follows

var ImgSlot = Backbone.Model.extend({
  defaults: {
  },
  schema: {
    imageField: {
      type: "Image"
    }
  }
})

Render form using:

this.form = new Backbone.Form({
  model: new ImgSlot(),
  submitButton: "Example Image file input handling"
}).render();

var errors = that.form.commit({validate: true})
if(errors != null)
  {
    return false;
  }
var data = that.form.model.attributes;
console.debug(data.imageField); // Will return base64 of image selected.
木森分化 2024-12-23 13:55:41

HTML5(包括 IE9)之前无法通过 AJAX 提交文件。

您需要通过 ajax 同步模型属性,然后使用该文件发送另一个 html 表单帖子,然后以某种方式同步它们。通常,通过ajax保存模型,获取id,将id添加到其他表单,然后发布文件。

“jquery.form”中的 jQuery 插件可以帮助您构建一个表单来发布文件。它管理“隐藏的 iframe 技巧”,因此对于最终用户来说它看起来就像 AJAX。

您可能只需要花一些时间谷歌搜索“隐藏的 iframe 技巧”......

It is not possible to submit a file over AJAX before HTML5 (including IE9).

You need to sync the model attributes over ajax, and then send another html form post with the file, and then sync them up somehow. Generally, save the model over ajax, get an id back, add the id to the other form, and then post the file.

The jQuery plug in "jquery.form" may help you to construct a form to post the file. It manages the "hidden iframe trick" so that it looks like AJAX to the end user.

You might just need to spend some time googling "hidden iframe trick" ...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文