如何从AWS S3下载大型文件,并重新启动网络损失

发布于 2025-02-10 15:00:09 字数 970 浏览 3 评论 0原文

我正在尝试从AWS S3存储桶实现“网络安全”下载器。 下载器应该能够从S3下载单个.zip文件并将其写入本地.zip文件。

我当前的方法是将节点与ReadStream和Writestream Ass一起使用,这是

const download = async () => {
    AWS.config.update(
        {
            accessKeyId: "",
            secretAccessKey: "",
            region: ""
        }
    );

    const s3 = new AWS.S3();

    const params = {
        Bucket: '',
        Key: ''
    };

    const { ContentLength: contentLength } = await s3.headObject(params).promise();

    const rs = s3.getObject(params).createReadStream()
    const ws = fs.createWriteStream(path.join('./', 'file.zip'));

    let progress = 0;

    rs.on('data', function (chunk) {
        progress += chunk.length;
        console.log(`Progress: ${progress / contentLength * 100}%`);
    });

    rs.pipe(ws);
}

我需要的一种方法,是一种捕获/创建有关网络错误的事件的方法,这将使我可以在网络重新开始时暂停并重新启动下载。 甚至更好 - 在恢复网络后自动重新启动下载。 目前,我找不到有关网络错误的任何事件,似乎在下载过程中的网络损失并不能触发“错误”事件。

节点/python中的任何解决方案都将非常适合

I am trying to implement a "network safe" downloader from aws s3 bucket.
the downloader should be able to download a single .zip file from s3 and write it to a local .zip file.

My current approach is using node with readStream and writeStream ass follows

const download = async () => {
    AWS.config.update(
        {
            accessKeyId: "",
            secretAccessKey: "",
            region: ""
        }
    );

    const s3 = new AWS.S3();

    const params = {
        Bucket: '',
        Key: ''
    };

    const { ContentLength: contentLength } = await s3.headObject(params).promise();

    const rs = s3.getObject(params).createReadStream()
    const ws = fs.createWriteStream(path.join('./', 'file.zip'));

    let progress = 0;

    rs.on('data', function (chunk) {
        progress += chunk.length;
        console.log(`Progress: ${progress / contentLength * 100}%`);
    });

    rs.pipe(ws);
}

what i need is a way to catch/create an event regarding network errors that will allow me to pause and restart the download when network is back on.
or even better - auto restart the download when network is restored.
currently i couldn't find any events regarding network errors and seems that network loss while download is in process does not triggers the 'error' event.

any solutions in node/python will be very appriciated

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

懷念過去 2025-02-17 15:00:09

简短更新:发现使用WGET将PresignedUrl下载到我要下载的对象上的工作。仍然不是我想拥有的本地经历。分享您的想法

export class Downloader {
    constructor(dest_dir, file_name_to_save) {
        this.dest_dir = dest_dir;
        this.file_name = file_name_to_save;
        this.progress = "61%"
    }

    async download_file(on_progress, on_done, socket, io) {

        let client = new S3Client({
            region: 'eu-west-1',
            credentials: {
                accessKeyId: "",
                secretAccessKey: "",
            }
        });

        const command = new GetObjectCommand({ Bucket: "s", Key: "" });
        const url = await getSignedUrl(client, command, { expiresIn: 3600 });



        let child = spawn('wget', ['-c', '-O', this.dest_dir + this.file_name, url]);

        socket.on('cancel', () => {
            child.kill()
            console.log("killed child")
        })

        child.stderr.on('data', (e) => {
            let stdout = e.toString();

            let p = stdout.match(/([0-9]+?\%)+/g);

            if (p && p.length > 0 && p[0] != this.progress) {
                on_progress && on_progress(p[0])
                console.log(p[0])
                this.progress = p[0]
            }
        });


        child.stdout.on('end', function (data) {
            on_done && on_done("end");
            console.log("end: ", data)
            child.kill();
        });

        child.on('exit', function (code) {
            if (code != 0) console.log('Failed: ' + code);
            else console.log("success!", code)

            on_done && on_done("exit");
        });
    }
}

Short update: found a work around using wget to download a preSignedUrl to the object i want to download. still not the native experience i wanted to have. share your thoughts

export class Downloader {
    constructor(dest_dir, file_name_to_save) {
        this.dest_dir = dest_dir;
        this.file_name = file_name_to_save;
        this.progress = "61%"
    }

    async download_file(on_progress, on_done, socket, io) {

        let client = new S3Client({
            region: 'eu-west-1',
            credentials: {
                accessKeyId: "",
                secretAccessKey: "",
            }
        });

        const command = new GetObjectCommand({ Bucket: "s", Key: "" });
        const url = await getSignedUrl(client, command, { expiresIn: 3600 });



        let child = spawn('wget', ['-c', '-O', this.dest_dir + this.file_name, url]);

        socket.on('cancel', () => {
            child.kill()
            console.log("killed child")
        })

        child.stderr.on('data', (e) => {
            let stdout = e.toString();

            let p = stdout.match(/([0-9]+?\%)+/g);

            if (p && p.length > 0 && p[0] != this.progress) {
                on_progress && on_progress(p[0])
                console.log(p[0])
                this.progress = p[0]
            }
        });


        child.stdout.on('end', function (data) {
            on_done && on_done("end");
            console.log("end: ", data)
            child.kill();
        });

        child.on('exit', function (code) {
            if (code != 0) console.log('Failed: ' + code);
            else console.log("success!", code)

            on_done && on_done("exit");
        });
    }
}

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文