技術架構
前端 (HTML5/JS) 後端 (Java)
┌─────────────────┐ ┌─────────────────┐
│ getUserMedia() │ │ ZXing Library │
│ 獲取視頻流 │ ──▶ │ 解析二維碼 │
│ Canvas 截幂 │ │ 返回業務數據 │
└─────────────────┘ └─────────────────┘
前端實現:HTML5 拍照上傳
<video id="video" width="320" height="240" autoplay playsinline></video>
<canvas id="canvas" width="320" height="240" style="display:none"></canvas>
<button id="scanBtn">掃描二維碼</button>
<script>
const video = document.getElementById('video');
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
// 1. 請求攝像頭權限
navigator.mediaDevices.getUserMedia({
video: { facingMode: 'environment' } // 後置攝像頭
}).then(stream => {
video.srcObject = stream;
}).catch(err => {
console.error('攝像頭訪問失敗:', err);
});
// 2. 掃描按鈕點擊
document.getElementById('scanBtn').addEventListener('click', () => {
ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
const imageData = canvas.toDataURL('image/png');
// 3. 上傳到後端解析
fetch('/api/qr/decode', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ image: imageData })
}).then(res => res.json())
.then(data => {
if (data.success) {
alert('掃描結果: ' + data.content);
// 觸發業務邏輯
}
});
});
</script>
後端實現:ZXing 解碼
@RestController
@RequestMapping("/api/qr")
public class QRController {
@PostMapping("/decode")
public Result decode(@RequestBody Map payload) {
String base64Image = payload.get("image");
// 移除 data:image/png;base64, 前綴
String base64Data = base64Image.split(",")[1];
byte[] imageBytes = Base64.getDecoder().decode(base64Data);
try (InputStream is = new ByteArrayInputStream(imageBytes)) {
BufferedImage image = ImageIO.read(is);
// ZXing 解碼
BinaryBitmap bitmap = new BinaryBitmap(
new HybridBinarizer(new BufferedImageLuminanceSource(image))
);
Result result = new MultiFormatReader().decode(bitmap);
return Result.success(result.getText());
} catch (Exception e) {
return Result.error("二維碼識別失敗: " + e.getMessage());
}
}
}
Maven 依賴
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.5.1</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.5.1</version>
</dependency>
關鍵注意點
- HTTPS 必須:
getUserMedia 需安全上下文 (localhost 除外)
- 權限處理:用戶拒絕攝像頭權限時的降級方案 (文件上傳)
- 性能優化:降低視頻分辨率、限制掃描頻率、Worker 線程解碼
- 兼容性:iOS Safari 需
playsinline、用戶交互後才能啟動攝像頭
參考資源