You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NodeJS上传视频至Blogger遇阻:视频数据未传输问题求助

Blogger视频上传问题:bytesTransferred始终为0

我尝试用以下NodeJS代码向Blogger上传视频,请求能获取响应,但视频数据无法传输,返回的响应中bytesTransferred字段显示为0,说明视频数据未被传输。

我的NodeJS代码

const axios = require('axios');
const fs = require('fs');
const path = require('path');

const videoPath = '/Downloads/11H3Bepq6Hx_seEhq2iO7OSW1zC01PnKo.mp4';
const videoStream = fs.createReadStream(videoPath);

let data = '{"protocolVersion":"0.8","createSessionRequest":{"fields":[{"external":{"name":"file","filename":"11H3Bepq6Hx_seEhq2iO7OSW1zC01PnKo.mp4","put":{},"size":1018020}},{"inlined":{"name":"title","content":"11H3Bepq6Hx_seEhq2iO7OSW1zC01PnKo.mp4","contentType":"text/plain"}},{"inlined":{"name":"addtime","content":"1726417159033","contentType":"text/plain"}},{"inlined":{"name":"onepick_version","content":"v2","contentType":"text/plain"}},{"inlined":{"name":"onepick_host_id","content":"10","contentType":"text/plain"}},{"inlined":{"name":"onepick_host_usecase","content":"RichEditor","contentType":"text/plain"}},{"inlined":{"name":"tos","content":"true","contentType":"text/plain"}},{"inlined":{"name":"blogID","content":"add-your-own-id-here","contentType":"text/plain"}},{"inlined":{"name":"postID","content":"add-your-own-id-here","contentType":"text/plain"}}]}}';

let config = {
    method: 'post',
    url: 'https://docs.google.com/upload/blogger/resumable?authuser=0&opi=98421741',
    headers: {
        'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8',
        'Accept': '*/*',
        'Sec-Fetch-Site': 'same-origin',
        'Accept-Language': 'en-IN,en-GB;q=0.9,en;q=0.8',
        'Accept-Encoding': 'gzip, deflate, br',
        'Sec-Fetch-Mode': 'cors',
        'Host': 'docs.google.com',
        'Origin': 'https://docs.google.com',
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.6 Safari/605.1.15',
        'Referer': 'https://docs.google.com/',
        'Content-Length': '860',
        'Connection': 'keep-alive',
        'Sec-Fetch-Dest': 'empty',
        'Cookie': '',
        'X-Goog-Upload-Header-Content-Type': 'video/mp4',
        'X-Goog-Upload-Header-Content-Length': '1018020',
        'X-Client-Pctx': 'CgcSBWjtl_cu',
        'X-Goog-Upload-Protocol': 'resumable',
        'X-Goog-Upload-Command': 'start'
    },
    data: data
};

axios.request(config)
    .then((response) => {
        console.log(JSON.stringify(response.data));
        
        const boundary = '----WebKitFormBoundary7MA4YWxkTrZu0gW';
        const body = `--${boundary}\r\n` +
            `Content-Disposition: form-data; name="metadata"\r\n\r\n` +
            `${data}\r\n` +
            `--${boundary}\r\n` +
            `Content-Disposition: form-data; name="Filedata"; filename="${path.basename(videoPath)}"\r\n` +
            `Content-Type: video/mp4\r\n` +
            `Content-Transfer-Encoding: binary\r\n\r\n` +
            `${fs.readFileSync(videoPath, { encoding: 'binary' })}\r\n` +
            `--${boundary}--`;

        let config = {
            method: 'post',
            url: `https://docs.google.com/upload/blogger/resumable?authuser=0&opi=98421741&upload_id=${response.data['sessionStatus']['upload_id']}&upload_protocol=resumable`,
            headers: {
                'Content-Type': `multipart/related; boundary=${boundary}`,
                'Accept': '*/*',
                'Sec-Fetch-Site': 'same-origin',
                'Accept-Language': 'en-IN,en-GB;q=0.9,en;q=0.8',
                'Accept-Encoding': 'gzip, deflate, br',
                'Sec-Fetch-Mode': 'cors',
                'Host': 'docs.google.com',
                'Origin': 'https://docs.google.com',
                'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.6 Safari/605.1.15',
                'Referer': 'https://docs.google.com/',
                'Content-Length': '1018020',
                'Connection': 'keep-alive',
                'Sec-Fetch-Dest': 'empty',
                'Cookie': '',
                "X-Goog-Upload-Protocol": "multipart",
            },
            "cache": "default",
            "credentials": "include",
            "mode": "cors",
            "redirect": "follow",
            "referrer": "https://docs.google.com/",
            "referrerPolicy": "origin",
            data: body
        };

        axios.request(config)
            .then((response) => {
                console.log(JSON.stringify(response.data));
            })
            .catch((error) => {
                console.log(error);
            });
    })
    .catch((error) => {
        console.log(error);
    });

Blogger返回的异常响应

{"sessionStatus":{"state":"FINALIZED","externalFieldTransfers":[{"name":"file","status":"COMPLETED","bytesTransferred":0,"bytesTotal":1018020,"putInfo":{"url":"https://docs.google.com/upload/blogger/resumable?authuser=0&opi=98421741&upload_protocol=resumable&upload_id=AD-8ljsco6WMZdutraflzfW1AtmJ1k5OYO2PudwjgaYof8PaCSqRn5kqZofxDnlNtVlaig95-jM&file_id=000"},"content_type":"video/mp4"}],"additionalInfo":{"uploader_service.GoogleRupioAdditionalInfo":{"completionInfo":{"status":"SUCCESS"}},"upload_id":"AD-8ljsco6WMZdutraflzfW1AtmJ1k5OYO2PudwjgaYof8PaCSqRn5kqZofxDnlNtVlaig95-jM"}}

可以看到bytesTransferred显示为0,说明视频数据未被传输。

浏览器上传的正常响应

{"sessionStatus":{"state":"FINALIZED","externalFieldTransfers":[{"name":"file","status":"COMPLETED","bytesTransferred":1018020,"bytesTotal":1018020,"putInfo":{"url":"https://docs.google.com/upload/blogger/resumable?authuser=0&opi=98421741&upload_id=AD-8ljvGMD4Mg6k6oSxW74UCa0gsZKJt3grXpwNS6UFtbCnu0D-HyPXF5_B_Krr1aJ-mZQjJ3jcicPLGUSAARAl4TJdDosvQiwltu-Xd139T0aI0&file_id=000"},"content_type":"video/mp4"}],"additionalInfo":{"uploader_service.GoogleRupioAdditionalInfo":{"completionInfo":{"status":"SUCCESS","customerSpecificInfo":{"contentId": "ed34314396d57090"}}}},"upload_id":"AD-8ljvGMD4Mg6k6oSxW74UCa0gsZKJt3grXpwNS6UFtbCnu0D-HyPXF5_B_Krr1aJ-mZQjJ3jcicPLGUSAARAl4TJdDosvQiwltu-Xd139T0aI0"}}

此处bytesTransferred与bytesTotal数值一致,均为1018020。

找到的参考代码

h.Xc = function() {
        var a = yd(this.Ca);
        this.V.length != null && (a["Content-Length"] = this.V.length);
        a = fac(a);
        a["X-Goog-Upload-Protocol"] = "multipart";
        a["Content-Type"] = "multipart/related; boundary=" + this.U;
        this.H = "Transferring";
        this.N = new DZ;
        this.O.te();
        this.O.listen(this.N, "progress", this.pda);
        this.O.listen(this.N, "complete", this.oda);
        var b = this.N,
            c = b.send,
            d = this.Ia,
            e = this.Ha,
            f = "--" + this.U + '\r\nContent-Disposition: form-data; name="metadata"\r\n\r\n' + (this.Ga + "\r\n--") + this.U + '\r\nContent-Disposition: form-data; name="Filedata"\r\nContent-Transfer-Encoding: ' +
            (this.La + "\r\n\r\n") + this.V + "\r\n--" + this.U + "--\r\n";
        this.wa = f.length - this.V.length;
        c.call(b, d, e, f, a)
    };

测试时需先登录Blogger获取Cookie值,同时将代码中data变量里的add-your-own-id-here替换为实际的博客ID和文章ID。

内容的提问来源于stack exchange,提问作者Karan Kankaria

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 07:22:03