Consider this JSFiddle . In it I select photos which I then want to base64 encode using canvas so I can store them in sessionStorage
for deferred uploading. Because I have it set for multiple files, I loop through each one and create an image and a canvas, but no matter what it just seems to output the exact same base64 encoded image every time. Through testing I know that on each loop iteration the image is different and does indeed point to a different file blob, but the canvas is just outputting the same thing over and over, which I think is also the last file in the files list. Sometimes it will also just output a "data," string and that's it. I'd love it if someone can point me in the right direction.
Code is show below:
HTML
<style type="text/css">
input[type="file"] {
display: none;
}
a {
display: inline-block;
margin: 6px;
}
</style>
<form action="#" method="post">
<input type="file" accept="image/*" multiple />
<button type="button">Select Photos</button>
</form>
<nav></nav>
JavaScript
console.clear(); $(function () { $("button[type=button]").on("click", function (e) { $("input[type=file]").trigger("click"); }); $("input[type=file]").on("change", function (e) { var nav = $("nav").empty(); for (var i = 0, l = this.files.length; i < l; i++) { var file = this.files[i], image = new Image(); $(image).on("load", i, function (e) { var canvas = document.createElement("canvas"), context = canvas.getContext("2d"); canvas.height = this.height; canvas.width = this.width; context.drawImage(this, 0, 0); nav.append("<a href=\\"" + canvas.toDataURL("image/jpeg") + "\\" target=\\"_blank\\">" + e.data + "</a>"); URL.revokeObjectURL(this.src); }); image.src = URL.createObjectURL(file); } }); });
but no matter what it just seems to output the exact same base64 encoded image every time.
.load()
event is asynchronous. You can use $.when()
, $.Deferred()
, substitute $.map()
for for
loop to handle asynchronously loaded img
elements. The caveat that the displayed a
element text may not be in numerical order; which can be adjusted by sorting the elements at .then()
; though not addressed at Question, if required, the listing or loading of images sequentially can also be achieved.
$("input[type=file]").on("change", function(e) {
var nav = $("nav").empty();
var file = this.files
$.when.apply($, $.map(file, function(img, i) {
return new $.Deferred(function(dfd) {
var image = new Image();
$(image).on("load", i, function(e) {
var canvas = document.createElement("canvas")
, context = canvas.getContext("2d");
canvas.height = this.height;
canvas.width = this.width;
context.drawImage(this, 0, 0);
nav.append("<a href=\""
+ canvas.toDataURL()
+ "\" target=\"_blank\">"
+ e.data + "</a>");
dfd.resolve()
URL.revokeObjectURL(this.src);
});
image.src = URL.createObjectURL(img);
return dfd.promise()
})
})).then(function() {
nav.find("a").each(function() {
console.log(this.href + "\n");
})
})
});
})
jsfiddle https://jsfiddle.net/bc6x3s02/19/
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.