Knockout JS: evento de descarga de files

Tengo este script knockout js para cargar el file

Este código activa el evento de carga cuando el usuario selecciona un file en el control de carga

Upload.html

$(function() { var viewModel = { filename: ko.observable(""), }; ko.applyBindings(viewModel); }); <form> <input id="upload" name="upload" data-bind="fileUpload: { property: 'filename', url: 'http://localhost/api/upload/PostFormData' }" type="file" /> <button id="submitUpload">Upload</button> </form> 

FileUpload.js

 ko.bindingHandlers.fileUpload = { init: function (element, valueAccessor) { $(element).after('<div class="progress"><div class="bar"></div><div class="percent">0%</div></div><div class="progressError"></div>'); }, update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) { var options = ko.utils.unwrapObservable(valueAccessor()), property = ko.utils.unwrapObservable(options.property), url = ko.utils.unwrapObservable(options.url); if (property && url) { $(element).change(function() { if (element.files.length) { var $this = $(this), fileName = $this.val(); // this uses jquery.form.js plugin $(element.form).ajaxSubmit({ url: url, type: "POST", dataType: "text", headers: { "Content-Disposition": "attachment; filename=" + fileName }, beforeSubmit: function() { $(".progress").show(); $(".progressError").hide(); $(".bar").width("0%") $(".percent").html("0%"); }, uploadProgress: function(event, position, total, percentComplete) { var percentVal = percentComplete + "%"; $(".bar").width(percentVal) $(".percent").html(percentVal); }, success: function(data) { //$(".progress").hide(); //$(".progressError").hide(); // set viewModel property to filename $("label[for='upload']").text(data); bindingContext.$data[property](data); }, error: function(jqXHR, errorThrown) { $(".progress").hide(); $("div.progressError").html(jqXHR.responseText); } }); } }); } } 

}

Ahora, quiero mover el desencadenante del evento de carga al button de envío

  <button id="submitUpload">Upload</button> 

¿Como hacer esto? Ahora mismo, aquí es donde estoy, solo muevo el evento de carga dentro del evento click del button. Pero no está funcionando, y no llama a la request de Ajax a la API.

  $('#submitUpload').click(function () { if (element.files.length) { var $this = $(element), fileName = $this.val(); //alert(element.form); // this uses jquery.form.js plugin $(element.form).ajaxSubmit({ url: url, type: "POST", dataType: "text", headers: { "Content-Disposition": "attachment; filename=" + fileName }, beforeSubmit: function() { $(".progress").show(); $(".progressError").hide(); $(".bar").width("0%") $(".percent").html("0%"); }, uploadProgress: function(event, position, total, percentComplete) { var percentVal = percentComplete + "%"; $(".bar").width(percentVal) $(".percent").html(percentVal); }, success: function(data) { //$(".progress").hide(); //$(".progressError").hide(); // set viewModel property to filename $("label[for='upload']").text(data); bindingContext.$data[property](data); }, error: function(jqXHR, errorThrown) { $(".progress").hide(); $("div.progressError").html(jqXHR.responseText); } }); } }); 

En lugar de pasar solo el nombre, la URL al tercer parámetro pase el manejador de encuadernación (fileBinaryData) de su object ViewModel, luego lea el file Content en el método de actualización de KO BindingHandler y luego actualice el tercer observable (fileBinaryData) en el método de actualización.

Entonces puede usar este file de datos en su model de vista

entonces, para el button, click evento y acceda al file BinaryData observable que tendrá el contenido del file.

Encuadernador:

 ko.bindingHandlers.FileUpload = { init: function (element, valueAccessor) { $(element).change(function () { var file = this.files[0]; if (ko.isObservable(valueAccessor())) { valueAccessor()(file); } }); }, update: function (element, valueAccessor, allBindingsAccessor) { var file = ko.utils.unwrapObservable(valueAccessor()); var bindings = allBindingsAccessor(); if (bindings.fileBinaryData && ko.isObservable(bindings.fileBinaryData)) { if (!file) { bindings.fileBinaryData(null); } else { var reader = new window.FileReader(); reader.onload = function (e) { bindings.fileBinaryData(e.target.result); }; reader.readAsBinaryString(file); } } } } 

HTML:

 <input type="file" id="fileUpload" class="file_input_hidden" data-bind="FileUpload: spFile, fileObjectURL: spFileObjectURL, fileBinaryData: spFileBinary" /> 

ViewModel:

 var viewModel = { filename: ko.observable(""), url: ko.observable(), spFileBinary:ko.observable(), //Write your CLICK EVENTS }; 

Espero que esto ayude 🙂

el elemento se desconoce en el momento del clic. necesitas encontrarlo en el formulario. Comience la primera línea de su function de clic con

 element = $('#upload').get(0); 

y reemplace su label de button con la siguiente

 <input type="button" id="submitUpload" value="Upload"></input> 

porque la label del button envía automáticamente el formulario.