HTML5 / Javascript是否支持将图片拖到网页上?
即
我是否可以创建一个网页,允许用户将图像从其他网站直接拖到我网站上的占位符(所有客户端),然后使用其他按钮将该图像上传回服务器?
答案 0 :(得分:3)
我无法确定所有浏览器在这种情况下的行为/做/将如何表现,但我所看到的是,当您从网页拖动图像并将其拖放到网页时(相同或另一个),浏览器不会从中创建文件(或Blob),只会创建它的标记。
这意味着在这种情况下您仍将受到跨源策略的束缚,即您将无法访问图像文件的数据,因此无法将其发送到您的服务器
但这不会阻止您在页面上显示此图片,也不会阻止您抓取src
。
所以你可以做的是处理两个案件:
<img>
元素,并将其src
设置为由文件制作的blobURI。text/html
项。如果是这样,请尝试解析它并查找现有的<img>
元素。如果有,您可以在当前文档中采用它们进行显示。但是,要将其保存在服务器上,您必须直接从服务器获取(不受同源策略限制),因此您必须将此URI发送到服务器。
var dropzone = document.getElementById('dropzone'),
send_btn = document.getElementById('send'),
res = document.getElementById('res'),
imgList = [];
dropzone.ondragover = function ondragover(e) {
e.preventDefault();
dropzone.classList.add('dragover');
};
dropzone.ondrop = function ondrop(e) {
e.preventDefault();
dropzone.classList.remove('dragover');
// try to get images from this dropevent
var imageObjects = retrieveImageData(e.dataTransfer);
if (!imageObjects) return;
imageObjects.forEach(function appendToDoc(imgObj) {
res.appendChild(imgObj.element);
});
// store it
imgList = imgList.concat(imageObjects);
if (imageObjects.length)
send_btn.disabled = false;
};
dropzone.ondragexit = function(ondragexit) {
dropzone.classList.remove('dragover');
};
function retrieveImageData(dT) {
// first try to get Files
var files = getFiles(dT);
if (files.length) {
return files;
}
// if none, try to get HTMLImage or SVGImage
var elems = getHTMLMarkup(dT);
if (elems && elems.length) {
return elems;
}
// we could also try to getData('text/plain') hoping for an url
// but this might not be such a good idea...
console.warn('unable to retrieve any image in dropped data');
}
function getFiles(dT) {
// quite simple: won't traverse folders
var files = [],
imgObj;
if (dT.files && dT.files.length) {
for (var i = 0; i < dT.files.length; i++) {
// only image Files
if (dT.files[i].type.indexOf('image/') === 0) {
imgObj = {
type: 'file',
element: new Image(),
file: dT.files[i]
};
imgObj.element.onerror = onIMGError;
imgObj.element.src = URL.createObjectURL(imgObj.file);
files.push(imgObj);
}
}
}
return files;
}
function getHTMLMarkup(dT) {
var markup = dT.getData('text/html');
if (markup) {
var doc = new DOMParser().parseFromString(markup, 'text/html');
var imgs = doc && doc.querySelectorAll('img,image') || [];
imgs.forEach(toImageObject);
return Array.prototype.map.call(imgs, toImageObject);
}
function toImageObject(element) {
var img;
if (element instanceof SVGImageElement) {
img = new Image();
img.src = element.getAttributeNS('http://www.w3.org/1999/xlink', 'href') ||
element.getAttribute('href');
} else {
img = document.adoptNode(element);
}
img.onerror = onIMGError;
return {
type: 'element',
element: img
};
}
}
// Once we got everything, time to retrieve our objects
send_btn.onclick = function sendData() {
var fD = new FormData();
// send Files data directly
var files = imgList.filter(function isFile(obj) {
return obj.type === 'file';
});
files.forEach(function appendToFD(obj) {
fD.append('files[]', obj.file);
});
// for elems, we will need to grab the data from the server
var elems = imgList.filter(function isElem(obj) {
return obj.type === "element";
});
var urls = elems.map(function grabURL(obj) {
return obj.element.src;
});
if (urls.length)
fD.append('urls', JSON.stringify(urls));
sendFormData(fD);
};
function sendFormData(fD) {
var xhr = new XMLHttpRequest();
xhr.open('POST', 'your_url');
// you would normally send it
//xhr.send(fD);
// but here we will just log the formData's content
var files = fD.getAll('files[]');
console.log('files: ', files);
var urls = fD.get('urls');
console.log('urls', urls);
}
// in case we can't load it
function onIMGError() {
var img = this;
var index = -1;
imgList.forEach(function search(obj, i) {
if (index < 0 && obj && obj.element === img)
index = i;
});
// remove from our list
if (index > -1) {
imgList.splice(index, 1);
if (img.parentNode) img.parentNode.removeChild(img);
}
}
#dropzone {
width: 300px;
height: 150px;
border: 1px solid black;
}
#dropzone.dragover {
background: rgba(0, 0, 0, .5);
}
#res {
border: 1px solid black;
}
<div id="dropzone">drop here</div>
<button id="send" disabled>log saved objects</button>
<div id="res">results:<br></div>
另请注意,contenteditable
容器的默认设置是显示此<img>
。我不想在这个足够长的例子中整合这个案例,但我确信你会找到一种方法来处理它。如果需要的话。