web呼叫攝像頭拍照並上傳到伺服器

我實在是太難了發表於2020-10-24

1.注意事項

1.網頁對攝像頭呼叫的限制比較高,要求網頁必須https協議或者是要本地localhost(127.0.0.1)否則無法呼叫,
2.當你的網頁協議是https請求的時候你向後端伺服器發的請求也是要https協議,否則也會出問題。
3.該專案是根據一個拍照識別商品並且展示3d產品的程式碼改的,有些東西看不懂可以無需理會。

2. 案例地址

案例地址

3. 前端全部程式碼

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>攝像頭拍照</title>
</head>
<style>
    body, html {
        margin: 0;
        height: 100%;
    }

    video {
        width: 100%;
        display: block;
    }

    #capture {
        position: absolute;
        top: 50%;
        left: 30px;
        transform: translateY(-50%);
        z-index: 2;
        font-weight: bold;
        font-size: 24px;
        opacity: 0.3;
        padding: 10px 20px;
        cursor: pointer;
    }

    canvas {
        display: block;
    }

    #lookModel {
        position: absolute;
        top: 50%;
        left: 50px;
        font-size: 50px;
        padding: 10px 20px;
        cursor: pointer;
        border-radius: 10px;
        border: solid 0px;
        opacity: 0.5;
        transform: translateY(-50%);
        display: none;
    }
</style>
<body>
<!--<video id="video"controls>-->
<div style="width: 600px; position: relative;">
    <button id="capture">拍照</button>
    <video id="video" style="width: 600px; position: relative;">
    </video>
</div>
<div id="html" style="position: absolute; top: 30px; right: 50px;">
</div>


<div style="display: block; position: relative;" id="none">
    <canvas id="canvas" width="480" height="320">
    </canvas>
    <button id="lookModel">模型混合現實</button>
</div>
<script src="./js/jquery-1.11.0.min.js"></script>
<script>
    document.getElementById('lookModel').onclick = function (ev) {
        location.href = './gltf.html'
    }

    //訪問使用者媒體裝置的相容方法
    function getUserMedia(constraints, success, error) {
        if (navigator.mediaDevices.getUserMedia) {
            //最新的標準API
            navigator.mediaDevices.getUserMedia(constraints).then(success).catch(error);
        } else if (navigator.webkitGetUserMedia) {
            //webkit核心瀏覽器
            navigator.webkitGetUserMedia(constraints, success, error)
        } else if (navigator.mozGetUserMedia) {
            //firfox瀏覽器
            navigator.mozGetUserMedia(constraints, success, error);
        } else if (navigator.getUserMedia) {
            //舊版API
            navigator.getUserMedia(constraints, success, error);
        }
    }

    let video = document.getElementById('video');
    let canvas = document.getElementById('canvas');
    let context = canvas.getContext('2d');

    function success(stream) {
        //相容webkit核心瀏覽器
        let CompatibleURL = window.URL || window.webkitURL;
        //將視訊流設定為video元素的源
        console.log(stream);

        //video.src = CompatibleURL.createObjectURL(stream);
        video.srcObject = stream;
        video.play();
    }

    function error(error) {
        console.log(`訪問使用者媒體裝置失敗${error.name}, ${error.message}`);
    }

    if (navigator.mediaDevices.getUserMedia || navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia) {
        //呼叫使用者媒體裝置, 訪問攝像頭
        getUserMedia({video: {width: 480, height: 320}}, success, error);
    } else {
        alert('不支援訪問使用者媒體');
    }

    document.getElementById('capture').addEventListener('click', function () {
        context.drawImage(video, 0, 0, 480, 320);

        function convertCanvasToImage(canvas) {
            var image = new Image();
            image.src = canvas.toDataURL("image/png");
            return image;
        }

        // let imgElement = convertCanvasToImage(canvas);
        // document.body.appendChild(imgElement)
        setTimeout(() => {
            send()
        }, 300)

    })

    function dataURItoBlob(base64Data) {
        var byteString;
        if (base64Data.split(',')[0].indexOf('base64') >= 0)
            byteString = atob(base64Data.split(',')[1]);
        else
            byteString = unescape(base64Data.split(',')[1]);
        var mimeString = base64Data.split(',')[0].split(':')[1].split(';')[0];
        var ia = new Uint8Array(byteString.length);
        for (var i = 0; i < byteString.length; i++) {
            ia[i] = byteString.charCodeAt(i);
        }
        return new Blob([ia], {type: mimeString});
    };

    //將blob轉換為file
    function blobToFile(theBlob, fileName) {
        theBlob.lastModifiedDate = new Date();
        theBlob.name = fileName;
        return theBlob;
    };

    function send() {
        //生成圖片格式base64包括:jpg、png格式
        var base64Data = canvas.toDataURL("image/jpeg", 1.0);
        //封裝blob物件
        var blob = dataURItoBlob(base64Data);

        var file = blobToFile(blob, "imgSignature");

        //這裡我打算用ajax方式,所以需要使用Formdata形式
        var data = new FormData();
        data.append("file", file);

        function ajax() {
            $.ajax({
                url: "http://localhost:3000/image2",
                type: "POST",
                dataType: "JSON",
                data: data,
                contentType: false,
                processData: false,
                success: function (res) {
                    let i = 0
                    console.log(res);
                    if (res.result.length == 0) return ajax() // 如果滅有找到重新找再次發請求
                    if (res.result[0].score > 0.6) {
                        document.getElementById('lookModel').style.display = 'block'
                        console.log('111: ', 111)
                    } else {
                        document.getElementById('lookModel').style.display = 'none'
                        console.log('222: ', 222)
                    }
                    document.getElementById('none').style.display = "block"
                    let html = ""
                    res.result.forEach((val) => {
                        html += `${++i}  檔名:***${Math.round(Math.random() * 10000)}****<br>相似度:${val.score}<br><br> `
                    })
                    $("#html").html(html)
                }, error(error) {
                    console.log('error: ', error)
                }
            });
        }

        ajax()
    }

</script>

</body>
</html>

4. java後端全部程式碼(maven工程專案)

伺服器配置

# application.yml 檔案程式碼。
server:
  port: 3000

  # 熱部署需新增的配置項
  devtools:
    restart:
      enabled: true
// 啟動類
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * 啟動類
 */
@SpringBootApplication
public class ImageApplication {
    public static void main(String[] args) {
        SpringApplication.run(ImageApplication.class,args);
    }
}
// controller層程式碼
@RestController
public class UploadController {

    @Autowired
    private UploadService uploadService;

    @PostMapping("/image2")
    public  ResponseEntity<String> uploadImage(MultipartHttpServletRequest request) throws IOException {
        MultipartFile file = request.getFile("file");
        String resultUrl;
        byte[] bytes = file.getBytes();
        resultUrl = uploadService.uploadImage( bytes, ".png");
        return ResponseEntity.ok(resultUrl);
    }
}

import ch.qos.logback.core.util.TimeUtil;
import com.mq.image.search.SimilarSearch;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

@Service
public class UploadService {

    // 本地上傳
    public String uploadFileToNginx2(byte[] file, String fix) {

        String ROOT_PATH = "D:\\deptuploadImage\\";
        File targetFile = new File(ROOT_PATH);
        if (!targetFile.exists()) {
            targetFile.mkdirs();
        }
        FileOutputStream out = null;
//        String fileName = UUID.randomUUID().toString();
        String fileName = "test";
        try {
            out = new FileOutputStream(ROOT_PATH + fileName + fix);
            out.write(file);
            out.flush();
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return fileName + fix;
    }

    public String uploadImage(byte[] file, String fix) {
        String path = uploadFileToNginx2(file, fix);
        return path;
    }
}

相關文章