在mjpeg img src中发送标头

时间:2018-02-12 09:57:54

标签: javascript stream xmlhttprequest fetch mjpeg

我想在src img属性的mjpeg网址中发送凭据HTTP标头。 由于不可能直接,我正在寻找一种方法来在我的反应应用程序中显示mjpeg流。

首先尝试:使用提取API

mjpeg(cameraId, cb) {
    const abortController = new AbortController();
    const signal = abortController.signal;
    fetch(this.endpoint + "camera/get/mjpeg/" + cameraId + "/", {
        method: "GET",
        headers: this.getHeaders(),
        mode: "cors",
        redirect: "follow",
        signal
    }).then((response) => {
        const reader = response.body.getReader();
        let imageBuffer = [];
        const stream = new ReadableStream({
            start(controller) {
                // The following function handles each data chunk
                const push = () => {
                    // "done" is a Boolean and value a "Uint8Array"
                    return reader.read().then(({ done, value }) => {
                        let i = 0;
                        while (i < value.length) {
                            if (i < (value.length - 2)) {
                                    // New image
                                    if (value[i] === 255 && value[i+1] === 216) {
                                        // console.log("jpeg found !");
                                        imageBuffer = [];
                                    }
                                    // End image
                                    if (value[i] === 255 && value[i+1] === 217) {
                                        // console.log("jpeg end !" + i + " / " + value.length);
                                        imageBuffer.push(value[i]);
                                        imageBuffer.push(value[i + 1]);

                                        const _arrayBufferToBase64 = (buffer) => {
                                            var binary = '';
                                            var bytes = new Uint8Array( buffer );
                                            var len = bytes.byteLength;
                                            for (var i = 0; i < len; i++) {
                                                binary += String.fromCharCode( bytes[ i ] );
                                            }
                                            return window.btoa( binary );
                                        };

                                        cb(null, false, _arrayBufferToBase64(imageBuffer));

                                        imageBuffer = [];
                                        i++;
                                    } else {
                                        imageBuffer.push(value[i]);
                                    }
                                } else {
                                    imageBuffer.push(value[i]);
                                }
                                i++;
                            }

                            // Protect buffer
                            if (imageBuffer.length > 4000000) {
                                imageBuffer = [];
                            }

                            // Is there no more data to read?
                            if (done) {
                                // Tell the browser that we have finished sending data
                                cb(null, true);
                                return;
                            }

                            // Get the data and send it to the browser via the controller

                            if (abortController.signal.aborted) {
                                throw Error("Stream aborted");
                            } else {
                                try {
                                    controller.enqueue(value);
                                } catch(e) {

                                }
                            }

                        }).then(push);
                    };

                    push();
            }
        });

        const abort = () => {
            stream.cancel();
            abortController.abort();
        };

        cb(null, false, null, abort);

        return new Response(stream, { headers: { "Content-Type": "image/jpeg" } });
    }).catch((error) => {
        cb(error, true);
    });
}

使用此代码,我可以在容器中成功显示图像,可以停止流(不干净 - 抛出异常)。 按预期工作,但仅适用于Chrome ,而非Safari或Firefox。

第二次尝试:使用XMLHttpRequest

我想用XMLHttpRequest做同样的过程。所以我可以手动添加标题并在传输过程中解密流。

但我有这些问题: Stream似乎仅适用于responseText,而非response。 我无法正确转换responseTextUint8Array

我想要一个带有流阅读器的fetch API解决方案,这在firefox / safari下根本不起作用。

有什么想法吗?

0 个答案:

没有答案