我正在尝试解决 ajax 过程中的问题,并且已回到基础知识。
我试图通过 ajax 将画布的 blob 内容发送到某个 php,但是当我尝试包含文件或 blob 时,我在 php 端得到“没有看到任何内容”,即使我看到一个 devtools 有效负载指示项目是已发送。
php 很简单:
<?php
if ( $_SERVER['REQUEST_METHOD']=='POST' ) {
$posts = "";
foreach ($_GET as $k => $v) $posts .= "<LI>(get) ".($k?$k:"null")."=[".($v?$v:"null")."]</LI>";
foreach ($_POST as $k => $v) $posts .= "<LI>(post) ".($k?$k:"null")."=[".($v?$v:"null")."]</LI>";
foreach ($_FILES as $k => $v) $posts .= "<LI>(file) ".($k?$k:"null")."</LI>";
if( $posts !== "" ) {
echo "<HR>PHP processing:<LI>$posts</LI>";
exit;
}
else echo "<HR>PHP processing:<LI>No post values detected</LI>";
exit;
}
?>
随之而来的 html 是:
const _AJAX_STATUS_OK=200;
//----------------------------------------------------------------------------------
function decodeEntities(html) {
var textarea = document.createElement("textarea");
textarea.innerHTML = html;
return textarea.value;
}
function getScriptName(exQ, exH, fullPath) {
if ( exQ==undefined ) exQ=true;
if ( exH==undefined ) exH=true;
if ( fullPath==undefined ) fullPath=true;
let result=location.href;
if ( exQ && result.indexOf('?')>0 ) result=result.substring(0,result.indexOf('?'));
if ( exH && result.indexOf('#')>0 ) result=result.substring(0,result.indexOf('#'));
if ( ! fullPath ) {
result=result.substring(result.lastIndexOf('/'));
}
return result;
}
function ajax(queryParams, destEl, formData, appendFg, url, postMethod) {
let dp;
let xhr;
let ap = appendFg;
if ( postMethod==undefined ) postMethod='POST';
if ( formData==undefined ) formData=new FormData();
if ( destEl ) dp = destEl;
if ( url==undefined ) url = getScriptName(true, true, true);
if (window.XMLHttpRequest) xhr = new XMLHttpRequest();
else if (window.ActiveXObject) xhr = new ActiveXObject('Microsoft.XMLHTTP');
else {
console.error("Your browser does not support Ajax");
return;
}
if (postMethod.toUpperCase() === 'GET') {
url = `${url}?${queryParams}`;
}
else if (postMethod.toUpperCase() === 'POST') {
const queryParamsEntries = new URLSearchParams(queryParams).entries();
for (const [key, value] of queryParamsEntries) {
console.log(`Appending ... ${key}=[${value}]`);
formData.append(key, value);
}
for (let [key, value] of formData.entries()) console.log('(pre-send) Resulting form key',key, value);
}
else {
console.error("Invalid action type. Use 'GET' or 'POST'.");
return;
}
let asyn=true;
xhr.open(postMethod, url, asyn);
xhr.onreadystatechange = function () {
if (xhr.readyState === XMLHttpRequest.DONE) {
if (xhr.status == _AJAX_STATUS_OK) {
if (xhr.responseText.indexOf('Fatal error') > -1 && doErrorAlerts) alert('process request err:' + xhr.responseText);
let update= new Array();
let respTxt= xhr.responseText;
respTxt = respTxt.replace(/{{BR}}/g, '\n');
respTxt = decodeEntities(respTxt);
if (dp) {
if ( ap ) dp.innerHTML += respTxt;
else dp.innerHTML = respTxt;
}
else {
console.debug('xhr result',respTxt);
console.log('xhr result',respTxt);
document.querySelector('#result').innerHTML+='<HR>Done (see console)';
}
}
}
};
if (postMethod.toUpperCase() === 'POST' && formData) {
if ( queryParams ) document.querySelector('#result').innerHTML+=`<LI>Sending queryParams:${queryParams}`;
for (let [key, value] of formData.entries()) {
document.querySelector('#result').innerHTML+=`<LI>Sending formData(${key})=${value}`;
}
xhr.send(formData);
}
else {
xhr.send();
}
}
// ----------------------------------------------------------
function doTest1() {
document.querySelector('#result').innerHTML='';
ajax("test=1&a=10&b=11", document.getElementById("result"));
}
function doTest2() {
document.querySelector('#result').innerHTML='';
var formData = new FormData();
formData.append('test', '2');
formData.append('a', '1');
formData.append('b', '2');
formData.append('c', '3');
formData.append('d', document.querySelector(`input[type='file']`).files[0]);
ajax(null, document.getElementById("result"), formData, true);
}
function doTest3a() {
document.querySelector('#result').innerHTML='';
doTestX('test=3&a=101', undefined, false);
}
function doTest3b() {
document.querySelector('#result').innerHTML='';
doTestX('test=4&a=102', document.getElementById("result"), false);
}
function doTest4a() {
document.querySelector('#result').innerHTML='';
doTestX('test=4&a=102', undefined, true);
}
function doTest4b() {
document.querySelector('#result').innerHTML='';
doTestX('test=4&a=102', document.getElementById("result"), true);
}
function doTestX(args, out, includeFile) {
const formData = new FormData();
if ( includeFile ) {
let img = document.querySelector('img');
let ft = 'png';
let canvas = document.createElement('canvas');
let ctx = canvas.getContext('2d');
canvas.width = img.naturalWidth;
canvas.height = img.naturalHeight;
ctx.drawImage(img, 0, 0);
const dataUrl = canvas.toDataURL();
const base64Data = dataUrl.split(',')[1];
const binaryString = atob(base64Data);
const uint8Array = new Uint8Array(binaryString.length);
for (let i = 0; i < binaryString.length; i++) {
uint8Array[i] = binaryString.charCodeAt(i);
}
const blob = new Blob([uint8Array], {type: 'image/' + ft});
formData.append('file', blob, 'canvas.' + ft);
}
ajax(args, out, formData, true);
}
function canvasToFile(canvas, fileName, mimeType) {
return new Promise((resolve, reject) => {
canvas.toBlob(function(blob) {
let file = new File([blob], fileName, { type: mimeType });
resolve(file);
}, mimeType);
});
}
window.addEventListener('load', async function(event) {
event.preventDefault();
let img = document.querySelector('img');
let ft = 'png';
let canvas = document.createElement('canvas');
let ctx = canvas.getContext('2d');
canvas.width = img.naturalWidth;
canvas.height = img.naturalHeight;
ctx.drawImage(img, 0, 0);
document.body.appendChild(canvas);
let file = await canvasToFile(canvas, 'canvasImage.'+ft, 'image/'+ft);
let dataTransfer = new DataTransfer();
dataTransfer.items.add(file);
let fileInput = document.getElementById('myfile');
fileInput.files = dataTransfer.files;
});
#result {
background-color: #d5d5d5;
padding:10px;
}
button {
margin:8px;
}
canvas {
width:25vw;
}
iframe {
border:none;
background-color:lightgrey;
}
Testing Ajax
<br>
<br>
<img style='width:50vw' src='/images/test-image.jpg'>
<br>
<br>
<form method="POST" target="resultFrame">
<input type="hidden" name="a" value="2001">
<input type="file" name="myfile" id="myfile" style="xdisplay:none">
<button>Submit form</button>
</form>
<div class="buttons">
<button onClick="doTest1()">Go1</button>
<button onClick="doTest2()">Go2 (with file)</button>
<br>
<button onClick="doTest3a()">Go3 ( /console)</button>
<button onClick="doTest3b()">Go3 ( /screen)</button>
<br>
<button onClick="doTest4a()">Go4 (with img /console)</button>
<button onClick="doTest4b()">Go4 (with img /screen)</button>
</div>
<pre id="result"></pre>
<iframe name="resultFrame"></iframe>
完整的代码可以在https://onlinephp.io/c/4677a上看到(但由于某种原因它无法运行)
如果我运行按钮 Go1,我会看到参数到达 php 并显示在灰色区域中。 如果我运行按钮 Go2 (带有文件),我会看到 formData 已建立 - 但 php 没有看到任何帖子。 我在 Go3 中进行了进一步的测试,它没有文件并且工作正常。 然后你有 Go4,它尝试包含一个文件,但像 Go2 一样,失败了。
我可以在开发工具有效负载中看到发送了一个文件、一个测试和一个 a(尽管在有效负载选项卡出现之前有可疑的延迟) - 但 php 没有看到/反映这些
我在这里做错了什么?