我尝试制作一种类似于 GMail 使用的图像上传功能。您从桌面复制 (CTRL-C) 图像并将其粘贴 (CTRL-V) 到网站上。 然后,图像通过 XMLHttpRequest 上传到处理传入文件的 php 脚本,其中“处理”意味着重命名并存储在服务器上。
我已经可以获取图像(和数据),但无法成功提交和接收 XMLHttpRequest。 我的 Javascript 代码如下所示:
document.onpaste = function(e){
var items = e.clipboardData.items;
console.log(JSON.stringify(items));
if (e.clipboardData.items[1].kind === 'file') {
// get the blob
var imageFile = items[1].getAsFile();
console.log(imageFile);
var reader = new FileReader();
reader.onload = function(event) {
console.log(event.target.result); // data url!
submitFileForm(event.target.result, 'paste');
};
}
};
function submitFileForm(file, type) {
var formData = new FormData();
formData.append('file', file);
formData.append('submission-type', type);
var xhr = new XMLHttpRequest();
xhr.open('POST', 'php/image-upload.php');
xhr.onload = function () {
if (xhr.status == 200) {
console.log('all done: ');
} else {
console.log('Nope');
}
};
xhr.send(formData);
}
处理 php (
php/image-upload.php
) 看起来像这样:
$base64string = $_POST['file'];
file_put_contents('img.png', base64_decode($base64string));
我认为
$_POST['file']
仍然是空的,但我不确定。
更重要的是,我还遇到“blob 大小”(用 console.log() 显示)比实际图像大小大得多。但也许这无关紧要或者是由编码引起的。
开发者控制台显示此内容。
{"0":{"type":"text/plain","kind":"string"},"1":{"type":"image/png","kind":"file"},"length":2} image-upload.js:8
Blob {type: "image/png", size: 135619, slice: function}
如果我通过右键单击实际图像文件来查看文件信息,它会显示大小
5,320 bytes (8 KB on disk)
。
我不一定需要使用
XMLHttpRequest
,这只是我首先想到的。如果有更好的方法用javascript实现图像实时上传到服务器,请告诉我们。
从桌面复制 (CTRL-C) 图像并将其粘贴 (CTRL-V) 到网站上。
不,那是不可能。您可以粘贴的内容例如来自网络的屏幕截图和图像,这就是 gmail 的作用。
您最大的错误是当您已经有一个文件时使用 FileReader,当存在正确的 HTTP 上传而不是临时的 base64 POST 参数时,
$_FILES
数组会被填充。要进行正确的 HTTP 上传,您只需 .append()
文件或 blob 对象(File
是 Blob
)。
这是一个独立的 PHP 文件,应该可以正常工作,托管该文件,将其打开为一个页面,截取屏幕截图,然后将其粘贴到页面上,几秒钟后图像应该出现在页面上。
<?php
if( isset( $_FILES['file'] ) ) {
$file_contents = file_get_contents( $_FILES['file']['tmp_name'] );
header("Content-Type: " . $_FILES['file']['type'] );
die($file_contents);
}
else {
header("HTTP/1.1 400 Bad Request");
}
print_r($_FILES);
?>
<script>
document.onpaste = function (e) {
var items = e.clipboardData.items;
var files = [];
for( var i = 0, len = items.length; i < len; ++i ) {
var item = items[i];
if( item.kind === "file" ) {
submitFileForm(item.getAsFile(), "paste");
}
}
};
function submitFileForm(file, type) {
var extension = file.type.match(/\/([a-z0-9]+)/i)[1].toLowerCase();
var formData = new FormData();
formData.append('file', file, "image_file");
formData.append('extension', extension );
formData.append("mimetype", file.type );
formData.append('submission-type', type);
var xhr = new XMLHttpRequest();
xhr.responseType = "blob";
xhr.open('POST', '<?php echo basename(__FILE__); ?>');
xhr.onload = function () {
if (xhr.status == 200) {
var img = new Image();
img.src = (window.URL || window.webkitURL)
.createObjectURL( xhr.response );
document.body.appendChild(img);
}
};
xhr.send(formData);
}
</script>
我已经发布了一个完整的工作示例。之前的问题是您需要正确构建 blob。通过将文件数据注入数组符号中
document.onpaste = function(e){
var items = e.clipboardData.items;
console.log(JSON.stringify(items));
if (e.clipboardData.items[0].kind === 'file') {
// get the blob
var imageFile = items[0].getAsFile();
console.log(imageFile);
var reader = new FileReader();
reader.onload = function(event) {
console.log(event.target.result); // data url!
submitFileForm(event.target.result, 'paste');
};
reader.readAsBinaryString(imageFile);
}
};
function submitFileForm(file, type) {
var formData = new FormData();
var myBlob = new Blob([file], { "type" : "image/png"} );
formData.append('file', myBlob, 'file.jpg');
formData.append('submission-type', type);
var xhr = new XMLHttpRequest();
xhr.open('POST', '/task/file');
xhr.onload = function () {
if (xhr.status == 200) {
console.log('all done: ');
} else {
console.log('Nope');
}
};
xhr.send(formData);
}
在这里您可以找到一个允许您上传图像或任何文件的网站,您将获得直接下载链接,将其粘贴到您的网站或博客上或与任何人分享,而无需浪费时间等待。它将生成直接下载链接。
在这里查看:https://upload.engrz.com
图像文件大小是否可能大于您的“upload_max_filesize”设置?(通常默认为 2 meg)
我猜该文件位于 $_FILE 数组中而不是 $_POST 中,因为它是一个文件。 如果没有,您可以将图像转换为字符串并将图像字符串作为 GET 请求发送。