' Caller 範例
ReDim stra(0) As String
stra(0) = o正規化.strBig5("") ' varchar_銷貨單號
Dim strSQL As String
strSQL = getStrSQL讀取單頭備註(stra)
Private Function getStrSQL讀取單頭備註(stra() As String) As String
'
' ' Caller 範例
' ReDim stra(0) As String
' stra(0) = o正規化.strBig5("") ' varchar_銷貨單號
' Dim strSQL As String
' strSQL = getStrSQL讀取單頭備註(stra)
'
'
' -- 原始 SQL 劇本 -- SQL Packager / SQL 打包器 於 2026-06-26 15:03:49 產生
'
'
' select top 1
' a.單頭備註
' from
' (select
' rtrim(單頭備註) as 單頭備註,
' 1 as 優先值
' from
' 銷貨單頭
' where
' 銷貨單號={{varchar,銷貨單號}}
'
' union all
'
' select
' '' as 單頭備註,
' 2 as 優先值
' ) as a
' order by
' a.優先值 asc
' 程式開始
Dim str1 As String
str1 = ""
str1 = str1 & vbCrLf
str1 = str1 & "select top 1"
str1 = str1 & vbCrLf
str1 = str1 & " a.單頭備註"
str1 = str1 & vbCrLf
str1 = str1 & "from"
str1 = str1 & vbCrLf
str1 = str1 & " (select "
str1 = str1 & vbCrLf
str1 = str1 & " rtrim(單頭備註) as 單頭備註,"
str1 = str1 & vbCrLf
str1 = str1 & " 1 as 優先值"
str1 = str1 & vbCrLf
str1 = str1 & " from"
str1 = str1 & vbCrLf
str1 = str1 & " 銷貨單頭"
str1 = str1 & vbCrLf
str1 = str1 & " where"
str1 = str1 & vbCrLf
str1 = str1 & " 銷貨單號="
str1 = str1 & stra(0) ' {{varchar_銷貨單號}}
str1 = str1 & vbCrLf
str1 = str1 & " "
str1 = str1 & vbCrLf
str1 = str1 & " union all"
str1 = str1 & vbCrLf
str1 = str1 & " "
str1 = str1 & vbCrLf
str1 = str1 & " select"
str1 = str1 & vbCrLf
str1 = str1 & " '' as 單頭備註,"
str1 = str1 & vbCrLf
str1 = str1 & " 2 as 優先值"
str1 = str1 & vbCrLf
str1 = str1 & " ) as a"
str1 = str1 & vbCrLf
str1 = str1 & "order by"
str1 = str1 & vbCrLf
str1 = str1 & " a.優先值 asc"
str1 = str1 & vbCrLf
getStrSQL讀取單頭備註 = str1
End Function
圖片檢視器ver1.16
<!doctype html>
<html lang="zh-Hant-TW">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<title>圖片檢視器 ver1.16</title>
<style>
html, body
{
margin: 0;
border: 0;
padding: 0;
width: 100vw;
height: 100vh;
overflow: hidden;
background-color: #f5f7df;
}
fieldset.classControlPanel
{
display: inline-block;
position: fixed;
z-index: 4;
left: 0;
top: 0;
margin: 0.5em;
border: 0;
border-radius: 6px;
padding: 0.5em;
background-color: #ffe3c4;
}
fieldset.classControlPanel > legend
{
font-family: 微軟正黑體, 標楷體;
font-weight: bold;
}
#aPara
{
font-size: 0.7em;
}
canvas.classFinalCanvas
{
position: fixed;
z-index: 3;
left: 0;
top: 0;
margin: 0;
border: 0;
padding: 0;
width: 100vw;
height: 100vh;
}
fieldset.classFSTransform,
fieldset.classFSDraw,
fieldset.classFSFile,
fieldset.classFSHelp
{
display: inline-block;
border-radius: 6px;
}
fieldset.classFSTransform legend,
fieldset.classFSDraw legend,
fieldset.classFSFile legend,
fieldset.classFSHelp legend
{
cursor: pointer;
}
div.classRealHide
{
display: none;
}
legend.classOpen::before
{
content: "-";
}
legend.classClose::before
{
content: "+";
}
</style>
</head>
<body onkeydown="bodyKeyDown(event);">
<fieldset class="classControlPanel">
<legend>圖片檢視器<a id="aPara"></a></legend>
<div>
<fieldset class="classFSFile">
<legend class="classOpen" title="點我切換顯示與隱藏" onclick="showHideBlock();">檔案</legend>
<div class="classShowHide">
<button type="button" onclick="loadOneImage();" title="載入圖片">載入</button>
<select id="selLayer" title="選取圖層">
<option title="原始圖片+繪畫圖層">融合</option>
<option title="純粹繪畫圖層">繪畫</option>
<option title="原始圖片">原始</option>
<option title="視窗所見圖層">最終</option>
</select>
<button type="button" onclick="exportToAFile();" title="匯出圖檔">匯出</button>
</div>
</fieldset>
<fieldset class="classFSTransform">
<legend class="classClose" title="點我切換顯示與隱藏" onclick="showHideBlock();">轉換</legend>
<div class="classShowHide classRealHide">
<button type="button" onclick="zoomIn();" title="放大圖片 [*]">大</button>
<button type="button" onclick="zoomOut();" title="縮小圖片 [/]">小</button>
<select id="selStep" title="選取移動步幅">
<option>1</option>
<option>2</option>
<option>4</option>
<option>8</option>
<option>16</option>
<option selected="true">32</option>
<option>64</option>
<option>128</option>
<option>256</option>
<option>512</option>
<option>1024</option>
<option>2048</option>
<option>4096</option>
</select>
<button type="button" onclick="moveLeft();" title="看左邊 [←]">左</button>
<button type="button" onclick="moveRight();" title="看右邊 [→]">右</button>
<button type="button" onclick="moveUp();" title="看上邊 [↑]">上</button>
<button type="button" onclick="moveDown();" title="看下邊 [↓]">下</button>
</div>
</fieldset>
<fieldset class="classFSDraw">
<legend class="classClose" title="點我切換顯示與隱藏" onclick="showHideBlock();">繪畫</legend>
<div class="classShowHide classRealHide">
<button type="button" onclick="switchDrawMode();" title="切換繪圖模式 [Ctrl+Draw]">切</button>
<select id="selDrawStyle" title="繪圖樣式">
<option selected="true">直線</option>
<option>空心矩形</option>
<option>實心矩形</option>
<option>空心圓形</option>
<option>實心圓形</option>
</select>
<select id="selTool" title="繪圖工具">
<option value="source-over" selected="true">彩筆</option>
<option value="destination-out">擦子</option>
</select>
<input type="color" id="inpDrawColor" value="#d10700" title="選取繪圖顏色">
<select id="selDrawWidth" title="選取線條寬度">
<option>1</option>
<option>2</option>
<option selected="true">4</option>
<option>8</option>
<option>16</option>
<option>32</option>
</select>
<button type="button" onclick="clearDrawCanvas();" title="清除繪畫圖層 [Ctrl+cleaR]">清</button>
<button type="button" onclick="switchAssistMode();" title="切換輔助線條 [Ctrl+Assist]">輔</button>
</div>
</fieldset>
<fieldset class="classFSHelp">
<legend class="classClose" title="點我切換顯示與隱藏" onclick="showHideBlock();">說明</legend>
<div class="classShowHide classRealHide">
最底層為原始圖片,<br>
中間層為繪畫圖層,(寬高與原始圖片相同)<br>
最上層為最終圖層。(寬高是視窗最大範圍)<br>
<br>
融合圖層是繪畫圖層+原始圖片,僅用在匯出時。
</div>
</fieldset>
</div>
</fieldset>
<canvas class="classFinalCanvas" onclick="clickFinalCanvas(event);" onmousemove="getCursorAndShowAssistLines();"></canvas>
<script> // toast
function toast(strMessage, iInterval)
{
if(!iInterval) { iInterval=2500; }
let oToast=document.createElement("div");
oToast.style.display="block";
oToast.style.position="fixed";
oToast.style.zIndex="6";
oToast.style.visibility="visible";
oToast.style.width="100%";
oToast.style.textAlign="center";
oToast.style.bottom="30px";
oToast.style.fontSize="17px";
let straStyle=[];
straStyle.push("display: inline-block");
straStyle.push("color: #ffffff");
straStyle.push("background-color: #333");
straStyle.push("margin: 0 auto");
straStyle.push("border-radius: 2px");
straStyle.push("padding: 16px");
oToast.innerHTML
="<div style='"+straStyle.join("; ")+"'>"
+strMessage
+"</div>";
document.body.appendChild(oToast);
window.setTimeout(function() { oToast.parentNode.removeChild(oToast); }, iInterval);
}
</script>
<script> // global parameters
var oImage=null;
var oDrawCanvas=null;
var oDrawCtx=null;
var oFinalCanvas=null;
var oFinalCtx=null;
let oPara={};
</script>
<script> // body key down
function bodyKeyDown(event)
{
console.log(event.key);
while(true)
{
if(event.key=='*') { zoomIn(); }
else if(event.key=='/') { zoomOut(); }
else if(event.key=='ArrowUp') { moveUp(); }
else if(event.key=='ArrowDown') { moveDown(); }
else if(event.key=='ArrowLeft') { moveLeft(); }
else if(event.key=='ArrowRight') { moveRight(); }
else if(event.key=='ArrowRight') { moveRight(); }
else if(event.ctrlKey==true && event.shiftKey==false && event.altKey==false && event.code=='KeyR') { clearDrawCanvas(); }
else if(event.ctrlKey==true && event.shiftKey==false && event.altKey==false && event.code=='KeyD') { switchDrawMode(); }
else if(event.ctrlKey==true && event.shiftKey==false && event.altKey==false && event.code=='KeyA') { switchAssistMode(); }
else { break; }
event.preventDefault();
break;
}
}
</script>
<script> // final canvas
function clearAndResizeFinalCanvas()
{
if(oFinalCanvas==null) { return; }
oFinalCanvas.setAttribute("width", "0");
oFinalCanvas.setAttribute("height", "0");
oFinalCanvas.setAttribute("width", String(document.documentElement.clientWidth));
oFinalCanvas.setAttribute("height", String(document.documentElement.clientHeight));
}
window.addEventListener(
"load",
async function()
{
oFinalCanvas=document.getElementsByClassName("classFinalCanvas")[0];
oFinalCtx=oFinalCanvas.getContext("2d");
clearAndResizeFinalCanvas();
}
);
function refreshFinalCanvas()
{
if(oImage==null) { return; }
if(oDrawCanvas==null) { return; }
if(oFinalCanvas==null) { return; }
let fX=oPara.fX;
let fY=oPara.fY;
let fW=oImage.width*oPara.fScale;
let fH=oImage.height*oPara.fScale;
let str繪圖樣式=document.getElementById("selDrawStyle").value;
clearAndResizeFinalCanvas(); // 清空畫面
oFinalCtx.drawImage(oImage, fX, fY, fW, fH); // 原始圖片
oFinalCtx.drawImage(oDrawCanvas, fX, fY, fW, fH); // 繪畫內容
if(oPara.booDraw==true && oPara.oaPoint.length==1) // 線條第一個點
{
let oPointFinalCanvas=from_image_to_final_canvas({x:oPara.oaPoint[0][0], y:oPara.oaPoint[0][1]});
oFinalCtx.beginPath();
oFinalCtx.strokeStyle="#3994e3";
oFinalCtx.lineWidth=2;
oFinalCtx.moveTo(oPointFinalCanvas.x-3, oPointFinalCanvas.y-3);
oFinalCtx.lineTo(oPointFinalCanvas.x+3, oPointFinalCanvas.y+3);
oFinalCtx.stroke();
oFinalCtx.moveTo(oPointFinalCanvas.x-3, oPointFinalCanvas.y+3);
oFinalCtx.lineTo(oPointFinalCanvas.x+3, oPointFinalCanvas.y-3);
oFinalCtx.stroke();
drawing(
oFinalCtx,
'source-over',
str繪圖樣式,
"#3994e3",
2,
oPointFinalCanvas.x,
oPointFinalCanvas.y,
oPara.oAssistPoint[0],
oPara.oAssistPoint[1]);
}
if(oPara.booAssist==true && oPara.oAssistPoint) // 輔助線條
{
oFinalCtx.beginPath();
oFinalCtx.strokeStyle="#ff0000";
oFinalCtx.lineWidth=1;
oFinalCtx.moveTo(oPara.oAssistPoint[0],0);
oFinalCtx.lineTo(oPara.oAssistPoint[0],oFinalCanvas.height);
oFinalCtx.stroke();
oFinalCtx.moveTo(0,oPara.oAssistPoint[1]);
oFinalCtx.lineTo(oFinalCanvas.width, oPara.oAssistPoint[1]);
oFinalCtx.stroke();
}
}
</script>
<script> // 座標系統轉換
function from_image_to_final_canvas(oPointImage)
{
if(oFinalCanvas==null) { return; }
let oRect=oFinalCanvas.getBoundingClientRect();
return {
x:oRect.left+oPara.fX+oPointImage.x*oPara.fScale,
y:oRect.top+oPara.fY+oPointImage.y*oPara.fScale
};
}
function from_final_canvas_to_image(oPointFinalCanvas)
{
if(oFinalCanvas==null) { return; }
let oRect=oFinalCanvas.getBoundingClientRect();
return {
x:(oPointFinalCanvas.x-oRect.left-oPara.fX)/oPara.fScale,
y:(oPointFinalCanvas.y-oRect.top-oPara.fY)/oPara.fScale
};
}
</script>
<script> // load one image
async function loadOneImage()
{
let oElement=document.createElement("input");
oElement.setAttribute("type", "file");
oElement.setAttribute("accept", "image/*");
oElement.addEventListener("change", loadImage);
oElement.click();
}
async function loadImage(event)
{
if(event.target.files.length<1)
{
toast("沒有選取圖檔,無法進行載入!");
return;
}
let oFile=event.target.files[0];
if(oFile.type.indexOf("image/")!=0)
{
toast("抱歉,您選取的檔案,並非瀏覽器支援的圖片格式,無法載入。");
return;
}
const oFileReader=new FileReader();
oFileReader.addEventListener(
"load",
function(event)
{
oImage=document.createElement("img");
oImage.addEventListener(
"load",
async function()
{
// 初始化 oDrawCanvas
oDrawCanvas=document.createElement("canvas");
oDrawCanvas.setAttribute("width", oImage.width);
oDrawCanvas.setAttribute("height", oImage.height);
oDrawCtx=oDrawCanvas.getContext('2d');
// 參數初始化
let fScaleW=document.documentElement.clientWidth/oImage.width;
let fScaleH=document.documentElement.clientHeight/oImage.height;
oPara.fScale=Math.min(fScaleW, fScaleH);
oPara.fX=0;
oPara.fY=0;
oPara.booDraw=false;
oPara.oaPoint=[];
oPara.booAssist=false;
refreshParameters(); // 刷新參數
refreshFinalCanvas(); // 繪製結果
showHideBlock(document.getElementsByClassName("classFSFile")[0].getElementsByTagName("legend")[0]);
}
);
oImage.src=event.target.result;
toast("圖片讀取完成。");
}
);
oFileReader.readAsDataURL(oFile);
}
</script>
<script> // refresh parameters
function refreshParameters()
{
if(oImage==null) { return; }
var stra1=[];
stra1.push("倍率("+oPara.fScale.toFixed(4)+")");
stra1.push("位移("+String(oPara.fX)+","+String(oPara.fY)+")");
if(oPara.booDraw==true)
{
stra1.push("繪圖-"+String(oPara.oaPoint.length)+"點");
}
document.getElementById("aPara").textContent=" "+stra1.join(" ");
}
</script>
<script> // zoom in/out and move left/right/up/down
function zoomIn()
{
if(oImage==null) { toast("尚未載入圖片"); return; }
oPara.fScale+=0.02;
refreshParameters();
refreshFinalCanvas();
}
function zoomOut()
{
if(oImage==null) { toast("尚未載入圖片"); return; }
oPara.fScale-=0.02;
if(oPara.fScale<0.02) { oPara.fScale=0.02; }
refreshParameters();
refreshFinalCanvas();
}
function getFPixel()
{
return Number(document.getElementById("selStep").value);
}
function moveUp()
{
if(oImage==null) { toast("尚未載入圖片"); return; }
oPara.fY+=getFPixel();
refreshParameters();
refreshFinalCanvas();
}
function moveDown()
{
if(oImage==null) { toast("尚未載入圖片"); return; }
oPara.fY-=getFPixel();
refreshParameters();
refreshFinalCanvas();
}
function moveLeft()
{
if(oImage==null) { toast("尚未載入圖片"); return; }
oPara.fX+=getFPixel();
refreshParameters();
refreshFinalCanvas();
}
function moveRight()
{
if(oImage==null) { toast("尚未載入圖片"); return; }
oPara.fX-=getFPixel();
refreshParameters();
refreshFinalCanvas();
}
</script>
<script> // clear draw canvas
function clearDrawCanvas()
{
if(oImage==null) { toast("尚未載入圖片"); return; }
if(oDrawCanvas==null) { toast("繪畫圖層尚未初始化"); return; }
oDrawCanvas.setAttribute("width", "0");
oDrawCanvas.setAttribute("height", "0");
oDrawCanvas.setAttribute("width", String(oImage.width));
oDrawCanvas.setAttribute("height", String(oImage.height));
refreshFinalCanvas();
toast('已經清除繪畫圖層');
}
</script>
<script> // switch draw mode
function switchDrawMode()
{
oPara.booDraw=!oPara.booDraw;
oPara.oaPoint=[];
refreshParameters();
if(oPara.booDraw==true) { toast('進入繪畫模式', 2000); }
else { toast('離開繪畫模式', 2000); }
}
</script>
<script> // assist lines
function switchAssistMode()
{
oPara.booAssist=!oPara.booAssist;
if(oPara.booAssist==true) { toast('顯示輔助線條', 2000); }
else { toast('關閉輔助線條', 2000); }
refreshFinalCanvas();
}
function getCursorAndShowAssistLines()
{
oPara.oAssistPoint=[event.clientX, event.clientY];
if(oImage==null) { return; }
if(oPara.booDraw==false && oPara.booAssist==false) { return; }
refreshFinalCanvas();
}
</script>
<script> // 繪製圖形
function drawing(oCtx, strGlobalCompositeOperation, str繪圖樣式, strColor, fWidth, x1, y1, x2, y2)
{
if(str繪圖樣式=="直線")
{
oCtx.beginPath();
oCtx.globalCompositeOperation=strGlobalCompositeOperation;
oCtx.strokeStyle=strColor;
oCtx.lineWidth=fWidth;
oCtx.moveTo(x1, y1);
oCtx.lineTo(x2, y2);
oCtx.stroke();
oCtx.globalCompositeOperation='source-over';
}
else if(str繪圖樣式=="空心矩形")
{
oCtx.beginPath();
oCtx.globalCompositeOperation=strGlobalCompositeOperation;
oCtx.strokeStyle=strColor;
oCtx.lineWidth=fWidth;
oCtx.strokeRect(x1, y1, x2-x1, y2-y1);
oCtx.globalCompositeOperation='source-over';
}
else if(str繪圖樣式=="實心矩形")
{
oCtx.beginPath();
oCtx.globalCompositeOperation=strGlobalCompositeOperation;
oCtx.fillStyle=strColor;
oCtx.lineWidth=fWidth;
oCtx.fillRect(x1, y1, x2-x1, y2-y1);
oCtx.globalCompositeOperation='source-over';
}
else if(str繪圖樣式=="空心圓形")
{
oCtx.beginPath();
oCtx.globalCompositeOperation=strGlobalCompositeOperation;
oCtx.strokeStyle=strColor;
oCtx.lineWidth=fWidth;
let fRadius=Math.sqrt((x2-x1)**2+(y2-y1)**2);
oCtx.arc(x1, y1, fRadius, 0, 2 * Math.PI);
oCtx.stroke();
oCtx.globalCompositeOperation='source-over';
}
else if(str繪圖樣式=="實心圓形")
{
oCtx.beginPath();
oCtx.globalCompositeOperation=strGlobalCompositeOperation;
oCtx.strokeStyle=strColor;
oCtx.fillStyle=strColor;
oCtx.lineWidth=fWidth;
let fRadius=Math.sqrt((x2-x1)**2+(y2-y1)**2);
oCtx.arc(x1, y1, fRadius, 0, 2 * Math.PI);
oCtx.stroke();
oCtx.fill();
oCtx.globalCompositeOperation='source-over';
}
}
function clickFinalCanvas(event)
{
if(oImage==null) { return; }
if(oDrawCanvas==null) { return; }
if(oPara.booDraw==false) { return; }
let oPointImage=from_final_canvas_to_image({x:event.clientX, y:event.clientY});
oPara.oaPoint.push([oPointImage.x, oPointImage.y]);
console.log(oPointImage.x, oPointImage.y);
if(oPara.oaPoint.length==2)
{
let str繪圖樣式=document.getElementById("selDrawStyle").value;
let strColor=document.getElementById('inpDrawColor').value;
let fWidth=Number(document.getElementById('selDrawWidth').value);
let x1=oPara.oaPoint[0][0];
let y1=oPara.oaPoint[0][1];
let x2=oPara.oaPoint[1][0];
let y2=oPara.oaPoint[1][1];
drawing(oDrawCtx, document.getElementById("selTool").value, str繪圖樣式, strColor, fWidth, x1, y1, x2, y2);
oPara.oaPoint=[];
}
refreshParameters();
refreshFinalCanvas();
}
</script>
<script>
function showHideBlock(oTarget=null)
{
var oLegend=null;
if(oTarget!=null) { oLegend=oTarget; }
else { oLegend=event.target; }
let oFieldset=oLegend.parentNode;
let oDiv=oFieldset.getElementsByClassName("classShowHide")[0];
if(oDiv.classList.contains("classRealHide")==true)
{
oDiv.classList.remove("classRealHide");
oLegend.setAttribute("class", "classOpen");
}
else
{
oDiv.classList.add("classRealHide");
oLegend.setAttribute("class", "classClose");
}
}
</script>
<script>
function exportToAFileCore(oCanvas, strDefaultFilename)
{
oCanvas.toBlob(
async function tempfunc(oBlob)
{
const strUrl=URL.createObjectURL(oBlob);
const oAnchor=document.createElement("a");
oAnchor.href=strUrl;
oAnchor.download=strDefaultFilename;
oAnchor.click();
URL.revokeObjectURL(strUrl);
},
"image/png"
);
}
function exportToAFile()
{
if(oImage==null) { toast("尚未載入圖片"); return; }
let strTargetLayer=document.getElementById("selLayer").value;
if(strTargetLayer=="融合")
{
let oMergedCanvas=document.createElement("canvas");
oMergedCanvas.setAttribute("width", oImage.width);
oMergedCanvas.setAttribute("height", oImage.height);
let oMergedCtx=oMergedCanvas.getContext("2d");
oMergedCtx.drawImage(oImage, 0, 0, oImage.width, oImage.height); // 原始圖片
oMergedCtx.drawImage(oDrawCanvas, 0, 0, oImage.width, oImage.height); // 繪畫內容
exportToAFileCore(oMergedCanvas, "merged.png");
}
else if(strTargetLayer=="原始")
{
let oOrigionalCanvas=document.createElement("canvas");
oOrigionalCanvas.setAttribute("width", oImage.width);
oOrigionalCanvas.setAttribute("height", oImage.height);
let oOrigionalCtx=oOrigionalCanvas.getContext("2d");
oOrigionalCtx.drawImage(oImage, 0, 0, oImage.width, oImage.height); // 原始圖片
exportToAFileCore(oOrigionalCanvas, "original.png");
}
else if(strTargetLayer=="繪畫")
{
exportToAFileCore(oDrawCanvas, "draw.png");
}
else if(strTargetLayer=="最終")
{
exportToAFileCore(oFinalCanvas, "final.png");
}
else
{
alert("抱歉,遇到不知名的圖層("+strTargetLayer+"),無法匯出!");
}
}
</script>
</body>
</html>
批次轉 m4a 為 mp3
單檔轉換,原始指令
ffmpeg -i input.m4a -c:a libmp3lame -q:a 2 output.mp3
在 cmd 底下,批次轉檔
for /r %i in (*.m4a) do ffmpeg -i "%i" -c:a libmp3lame -q:a 2 "%~dpni.mp3"
在 batch (*.bat) 裡面,批次轉檔
for /r %%i in (*.m4a) do ffmpeg -i "%%i" -c:a libmp3lame -q:a 2 "%%~dpni.mp3"
javascript fetch + php + json + multi-files
01_fill.php
<!doctype html>
<html lang="zh-Hant-TW">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<title>上傳資料與多檔</title>
</head>
<body>
<div>
<div>備註<input type="text" id="inpNote"></div>
<div>檔案<input type="file" id="inpFiles" multiple></div>
<div><button type="button" onclick="uploadData();">上傳</button></div>
<div id="divResult"></div>
</div>
<script>
async function uploadData()
{
let oBtn=event.target;
oBtn.setAttribute("disabled", "true");
while(true)
{
let strNote=document.getElementById("inpNote").value;
let oFiles=document.getElementById("inpFiles");
let oFormData=new FormData();
oFormData.append("strJson", JSON.stringify({ "strNote": strNote }));
for(let i=0; i<oFiles.files.length; i++)
{
oFormData.append("oaFile[]", oFiles.files[i]);
}
try
{
var oResponse=await fetch("upload.php", { method: "POST", body: oFormData });
var strJson=await oResponse.text();
var oJson=JSON.parse(strJson);
document.getElementById("divResult").textContent=strJson;
}
catch(oError)
{
console.log({ "oResponse":oResponse, "strJson":strJson, "oError":oError });
alert((oResponse.url+"\n"+oResponse.status+"\n"+oResponse.statusText)+"\n\n"+strJson+"\r\n"+(oError.toString()));
break;
}
break;
}
oBtn.removeAttribute("disabled");
}
</script>
</body>
</html>
02_upload.php
<?php
header("Content-Type: application/json; charset=utf-8");
// 資料部份
$oJson=json_decode($_POST['strJson']);
// 檔案部份
$iFileCount=count($_FILES['oaFile']['name']);
for($i=0; $i<$iFileCount; $i++)
{
$strSrcFilePath=$_FILES['oaFile']['tmp_name'][$i];
$strSrcFileName=basename($_FILES['oaFile']['name'][$i]);
$strDstFilePath="uploadfiles/" . $strSrcFileName;
move_uploaded_file($strSrcFilePath, $strDstFilePath);
}
// 回傳json
$oOutData=new stdClass();
$oOutData->iFileCount=$iFileCount;
$oOutData->strNote=$oJson->strNote;
echo json_encode($oOutData, JSON_UNESCAPED_UNICODE); // 輸出 json 資料
?>
資料庫常用類別設計 MySQL,MariaDB,PHP 修正版
<?php
// modified:2026-06-04 11:31:00
// $oMySQL=new CMySQL();
// $oR=$oMySQL->insUpdDel("default", "insert into test(i1,vc1) select 1,'馬蓋仙' union all select 140,'老人家'");
// echo '<pre>';
// var_dump($oR);
// echo '</pre>';
// echo '<hr>';
// $oR=$oMySQL->bigQuery("default", "select 'q1',i1,vc1 from test where i1<=39; select 'q2',i1,vc1 from test where i1>39;");
// echo '<pre>';
// var_dump($oR);
// echo '</pre>';
class CMySQLSQLResult_unit
{
public $straFieldName=array();
public $booaTextType=array();
public $iRows=0;
public $iCols=0;
public $aryRawData=array();
public function getVal($iRow, $strFieldName)
{
$iCol=array_search($strFieldName, $this->straFieldName);
if($iCol===false) { return 'field name not found!'; }
if($iRow>=$this->iRows) { return 'row index out of range!'; }
return $this->aryRawData[$iRow][$iCol];
}
}
class CMySQLSQLResult
{
public $booInsUpdDel=false; // 增修刪=true, 大查詢=false
public $booSuccess=false;
public $strErrorMessage='';
// 增修刪↓
public $iAffectedRows=0;
// 大查詢↓
public $iResultAmount=0;
public $aryResult=array(); // 裝載 CMySQLSQLResult_unit 的陣列,用 array_push()
}
class CMySQL
{
public function getAryConnection($strWho)
{
// [customvalue]
if($strWho=='another') { return array('ip1','username1','password1','database1',3306,'utf8mb4'); }
else { return array('127.0.0.1','root','a/6u3u;35/4','dbChildmo',3306,'utf8mb4'); }
}
// 參數正規化,避免 SQL Injection
public function getStrNum($value) { return strval(floatval($value)); }
public function getStrNormalizedString($value) { return str_replace("'","''",$value); }
public function getStrAnsiTxt($value) { return "'" . $this->getStrNormalizedString($value) . "'"; }
public function getStrUniTxt($value) { return "'" . $this->getStrNormalizedString($value) . "'"; }
public function getStrAnsiLikeTxt($value) { return "'" . '%' . $this->getStrNormalizedString($value) . '%' . "'"; }
public function getStrUniLikeTxt($value) { return "'" . '%' . $this->getStrNormalizedString($value) . '%' . "'"; }
public function getStrFreeText($value) { return $value; }
public function insUpdDel($strWho, $strSQL)
{
$oR=new CMySQLSQLResult();
$oR->booInsUpdDel=true;
while(true)
{
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
// 連線到資料庫
list($strIP, $strUID, $strPWD, $strDB, $iPort, $strEncoding)=$this->getAryConnection($strWho);
$oConn=new mysqli($strIP, $strUID, $strPWD, $strDB, $iPort);
if($oConn->connect_errno)
{
$oR->booSuccess=false;
$oR->strErrorMessage='資料庫連線失敗!ErrMsg:' . $oConn->connect_error;
break;
}
while(true)
{
// 設定編碼
if($oConn->set_charset($strEncoding)==false)
{
$oR->booSuccess=false;
$oR->strErrorMessage='設定(' . $strEncoding . ')編碼失敗!';
break;
}
// 執行 SQL 指令劇本
if($oConn->query($strSQL)==false)
{
$oR->booSuccess=false;
$oR->strErrorMessage='資料庫異動失敗!ErrMsg:' . $oConn->error;
break;
}
// 取得資訊
$oR->booSuccess=true;
$oR->iAffectedRows=$oConn->affected_rows;
break;
}
// 釋放連線
$oConn->close();
break;
}
return $oR;
}
public function bigQuery($strWho, $strSQL)
{
$oR=new CMySQLSQLResult();
$oR->booInsUpdDel=false;
while(true)
{
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
// 連線到資料庫
list($strIP, $strUID, $strPWD, $strDB, $iPort, $strEncoding)=$this->getAryConnection($strWho);
$oConn=new mysqli($strIP, $strUID, $strPWD, $strDB, $iPort);
if($oConn->connect_errno)
{
$oR->booSuccess=false;
$oR->strErrorMessage='資料庫連線失敗!ErrMsg:' . $oConn->connect_error;
break;
}
while(true)
{
// 設定編碼
if($oConn->set_charset($strEncoding)==false)
{
$oR->booSuccess=false;
$oR->strErrorMessage='設定(' . $strEncoding . ')編碼失敗!';
break;
}
// 執行 SQL 指令劇本
if($oConn->multi_query($strSQL)==false)
{
$oR->booSuccess=false;
$oR->strErrorMessage='資料庫異動失敗!ErrMsg:' . $oConn->error;
break;
}
// 逐個結果集檢視
$oR->booSuccess=true;
while(true)
{
// 讀取資料集
$oResult=$oConn->store_result();
if($oResult===false)
{
// 例如 set @x=1; 也會傳回查詢成功,但無結果集,僅做個記錄。放在 errormessage ,不破壞之前的結構。
$oR->strErrorMessage=$oR->strErrorMessage . '(' . $oConn->connect_error . ')';
}
else
{
// 新增一個單元
$oR->iResultAmount++;
$oUnit=new CMySQLSQLResult_unit();
$oUnit->iCols=$oResult->field_count;
$oUnit->iRows=$oResult->num_rows;
$oFieldInfo=$oResult->fetch_fields();
for($i=0; $i<$oUnit->iCols; $i++)
{
$oUnit->straFieldName[]=$oFieldInfo[$i]->name;
$oUnit->booaTextType[]=in_array($oFieldInfo[$i]->type, array(MYSQLI_TYPE_VAR_STRING,MYSQLI_TYPE_STRING,MYSQLI_TYPE_CHAR,MYSQLI_TYPE_TINY_BLOB,MYSQLI_TYPE_MEDIUM_BLOB,MYSQLI_TYPE_LONG_BLOB,MYSQLI_TYPE_BLOB));
}
while($oRow=$oResult->fetch_row())
{
$oUnit->aryRawData[]=$oRow;
}
$oR->aryResult[]=$oUnit;
// 釋放資料集資源
$oResult->free_result();
}
// 查看是否還有資料集
if($oConn->more_results()==false) { break; }
// 準備前往下一個資料集
if($oConn->next_result()==false)
{
$oR->booSuccess=false;
$oR->strErrorMessage=$oR->strErrorMessage . '。資料集往下失敗!ErrMsg:' . $oConn->connect_error;
break;
}
}
break;
}
// 釋放連線
$oConn->close();
break;
}
return $oR;
}
}
?>