hey m using mvc3 with knockout and trying to use knockout binding to upload and save uploaded image in database. i am able to browse and get the image but not getting as how to save that image. my html view is:
<div data-bind="foreach: { data: images, beforeRemove: beforeRemoveSlot }">
<div>
<input type="file" accept="image/*" data-bind="file: imageFile, fileObjectURL: imageObjectURL, fileBinaryData: imageBinary"/>
<div data-bind="if: imageObjectURL">
<img class="thumb" data-bind="attr: { src: imageObjectURL }"/>
</div>
<div>Size: <span data-bind="text: fileSize"></span> bytes</div>
</div>
</div>
<input type="submit" value="Upload Picture" data-bind="click: upload" />
my view model is:
var windowURL = window.URL || window.webkitURL;
ko.bindingHandlers.file = {
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.fileObjectURL && ko.isObservable(bindings.fileObjectURL)) {
var oldUrl = bindings.fileObjectURL();
if (oldUrl) {
windowURL.revokeObjectURL(oldUrl);
}
bindings.fileObjectURL(file && windowURL.createObjectURL(file));
}
if (bindings.fileBinaryData && ko.isObservable(bindings.fileBinaryData)) {
if (!file) {
bindings.fileBinaryData(null);
} else {
var reader = new FileReader();
reader.onload = function (e) {
bindings.fileBinaryData(e.target.result);
};
reader.readAsArrayBuffer(file);
}
}
}
};
var imageUploadModel = function () {
var self = {};
var slotModel = function () {
var that = {};
that.imageFile = ko.observable();
that.imageObjectURL = ko.observable();
that.imageBinary = ko.observable();
that.fileSize = ko.computed(function () {
var file = this.imageFile();
return file ? file.size : 0;
}, that);
that.firstBytes = ko.computed(function () {
if (that.imageBinary()) {
var buf = new Uint8Array(that.imageBinary());
var bytes = [];
for (var i = 0; i < Math.min(10, buf.length); ++i) {
bytes.push(buf[i]);
}
return '[' + bytes.join(', ') + ']';
} else {
return '';
}
}, that);
return that;
};
self.beforeRemoveSlot = function (element, index, data) {
if (data.imageObjectURL()) {
windowURL.revokeObjectURL(data.imageObjectURL());
}
$(element).remove();
};
self.images = ko.observableArray([slotModel()]);
self.addSlot = function () {
self.images.push(slotModel());
};
self.removeSlot = function (data) {
self.images.remove(data);
};
return self;
} ();
imageUploadModel.upload = function () {
}
$(document).ready(function () {
ko.applyBindings(imageUploadModel);
});
can anybody suggest me how can i save image on upload button click?????
here's an example of single click image uploads via knockout I've scrubbed together
html ->
<input type="file" data-bind="value: fileName, fileUpload: fileName, url: url">
<script src="{{ STATIC_URL }}html5knockoutImagePreview.js"></script>
js ->
ko.bindingHandlers.fileUpload = {
update: function(element, valueAccessor, allBindingsAccessor){
var value = ko.utils.unwrapObservable(valueAccessor())
if(element.files.length && value){
var file = element.files[0];
var url = allBindingsAccessor().url
xhr = new XMLHttpRequest();
xhr.open("post", url, true);
xhr.setRequestHeader("Content-Type", "image/jpeg");
xhr.setRequestHeader("X-File-Name", file.name);
xhr.setRequestHeader("X-File-Size", file.size);
xhr.setRequestHeader("X-File-Type", file.type);
console.log("sending")
// Send the file (doh)
xhr.send(file);
}
}
}
function MainPageViewModal(){
this.fileName = ko.observable()
this.url = "http://127.0.0.1:8000/upload"
}
var mainPageViewModal = new MainPageViewModal()
ko.applyBindings(mainPageViewModal);
fiddle
I'm not 100% sure of all your requirements, this is for jpegs, you need to tweak the content type header for other types etc.
Edit
As you're continuing to have issues, here's some code that I've written since then that might help. It does use jquery though...
ko bindings ->
ko.bindingHandlers.filePreview = {
update: function(element, valueAccessor, allBindingsAccessor){
var allBindings = allBindingsAccessor()
if(!!FileReader && valueAccessor() && element.files.length){
var reader = new FileReader();
reader.onload = function(event){
var dataUri = event.target.result
allBindings.imagePreview(dataUri)
}
reader.onerror = function(e) {
console.log("error", stuff)
}
reader.readAsDataURL(element.files[0])
}
}
}
modelPageView ->
, uploadPreview: function(files){
var self = this
self.loadingPreview(true)
file = files[0]
if(file.size > 20000000){
alert("that image is a bit too big for us, got anything smaller?")
}
console.log("file size " + file.size)
var formData = new FormData();
formData.append("img", file)
$.ajax({
url: "/YOUR_UPLOAD_URL",
type: 'POST',
data: formData,
cache: false,
contentType: false,
processData: false
}).done(function(data){
if(data === "error"){
alert("somethign wrong happened, please refresh the page")
return
}
self.imgUrl(data.img_url)
self.imgId(data.img_id)
}).fail(function(){
self.loadingPreview(false)
})
}
html ->
<input type="file" accept="image/*" name="img" data-bind="value: img, fileAdded: img, previewFunc: function(files){ $data.uploadPreview(files) }" />
Sorry about the delay in replying, I'll take a peak in a couple of days, so let me know if you're still having issues.
Good Luck!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With