我正在使用FormData
API。 Here是我正在使用的小提琴 - 我正在尝试将blob注入到我的表单中并通过AJAX提交。
//ic0 and tc0 are canvases
//image0 and thumb0 are file inputs
function ajaxSubmit(){
var fd = new FormData(document.forms[0]);
ic0.toBlob(
function(blob){
fd.set("image0", blob, "image0.jpg");
}, "image/jpeg", 0.7);
tc0.toBlob(
function(blob){
fd.set("thumb0", blob, "thumb0.jpg");
}, "image/jpeg", 0.7);
var xhr = new XMLHttpRequest();
xhr.open("POST", "/ajax-upload/", true);
xhr.send(fd);
}
浏览器行为有点......奇怪:
无法做到,给出:
Failed blob:https%3A//fiddle.jshell.net/uuid4 to load resource: the server responded with 404
但我认为FormData.set()
现在得到了支持?它似乎适用于非blob?
如果FormData()
对象未使用已经具有必要文件输入的DOM对象进行初始化(但是已发布附加的正常输入),则似乎不起作用。 FormData.set()
似乎不适用于文件输入和blob(您会注意到thumb0
在有效负载中为空,尽管在其上调用了fd.set("thumb0", blob, "thumb0.jpg")
。您可以通过执行{来验证它是否已设置} {1}}设置完成后,您还会注意到console.log(fd.get("thumb0"))
的有效负载错误地是原始图像,而不是调整大小的画布图像。
使用javascript无法自定义多部分image0
是不方便的。我是一个javascript noob - 我在这里做了一些完全错误,或者这些浏览器没有正确支持FormData
API?如何在我的小提琴中正确提交FormData
和image0
?
编辑:好的,请给予赏金。我知道有很多依赖于jquery的库,比如blueimp,我认为它们是基于64的数据,而不是作为文件输入传输(加上我想避免使用jquery)。我只需要为这个项目支持最新的Chrome或Firefox,我真的希望我能保持代码干净,因为thumb0
API似乎建议我可以。任何人都可以成功地从画布上获取图像并将其作为文件插入POST有效负载吗?我希望能够在django的FormData
中访问它。
答案 0 :(得分:3)
我认为你在这里缺少的一件事是javascript的异步性质。在ajaxSubmit
方法 -
function ajaxSubmit(){
var fd = new FormData(document.forms[0]);
ic0.toBlob(function(blob){
fd.set("image0", blob, "image0.jpg");
}, "image/jpeg", 0.7); // this call is asynchronous
tc0.toBlob(function(blob){
fd.set("thumb0", blob, "thumb0.jpg");
}, "image/jpeg", 0.7); // this call is also asynchronous
/*
hence the below code may get executed before
fd.set("image0", blob, "image0.jpg");
this statement. which it does.
that is why the canvas files are not submitted.
*/
var xhr = new XMLHttpRequest();
xhr.open("POST", "/ajax-upload/", true);
xhr.send(fd);
}
尝试同步代码
function ajaxSubmit(){
var fd = new FormData(document.forms[0]);
ic0.toBlob(function(blob){
fd.set("image0", blob, "image0.jpg");
tc0.toBlob(function(blob){
fd.set("thumb0", blob, "thumb0.jpg");
console.log(blob);
console.log("Just blobbed thumb0");
var xhr = new XMLHttpRequest();
xhr.open("POST", "fileuploadbackend.jsp", true);
//xhr.setRequestHeader("X-CSRFToken", csrftoken);
xhr.send(fd);
}, "image/jpeg", 0.7);
}, "image/jpeg", 0.7);
}
同样 jornare 建议您注释掉
行URL.revokeObjectURL(img.src);
导致chrome出错。加载图像完成后调用它。
你也有多个具有相同身份的元素,
<input id="image0" name="image0" type="file" />
<label for="image0">image0</label>
<input id="image0" name="thumb0" type="file" />
这不会在您的代码中产生问题,但ID应该是不同的。
<强>更新强>
这是工作fiddle。
注意:将请求网址更改为相应的网址。
请按照以下链接深入了解javascript的异步行为以及如何处理AJAX请求回调。
答案 1 :(得分:1)
通过你的小提琴,你在加载之前清理了dataURL,因此缩略图根本没有加载。 (404)
我做了一个更新的小提琴https://jsfiddle.net/tLqch5x2/3/
function handleFiles(e){
var img = new Image();
img.onload = function(){
var width = 30;
var height = img.height * 30/img.width;
e.target.ic0.width = width ;
e.target.ic0.height = height ;
e.target.tc0.width = width/2 ;
e.target.tc0.height = height/2;
var ctx = e.target.ic0.getContext("2d");
ctx.drawImage(img, 0, 0, width, height);
ctx = e.target.tc0.getContext("2d");
ctx.drawImage(img, 0, 0, width/2, height/2);
URL.revokeObjectURL(img.src); //clean up memory here instead
};
img.src = URL.createObjectURL(e.target.files[0]);
//clean up to prevent memory leak
//URL.revokeObjectURL(img.src); //too soon
}
它仍有404,但现在尝试发布到jsfiddle.net上不存在的网址。请在您的环境中试一试。
请注意,html和代码中也有一些其他细微的变化。 (不正确地命名图像,在创建提交的新表单时无需引用现有表格)