使用Nodejs分块上传大文件

5
我正在尝试以分块的方式将非常大的文件上传到服务器。服务器端工作得很好。在我想出的函数中,它尝试一次性上传所有文件。我对async/await不熟悉,不确定该如何继续进行。目标是逐个以块的形式上传。

请注意,我从一个类中剥离了这段代码,以增加清晰度并删除了所有不必要的部分。

使用node-fetch添加fetch()功能。

感谢任何帮助或建议:)

let tree = []

const start = () => {
    scan('/foo/bar', err => { 
        tree.forEach(file => {
            upload(file)
        })
    })
}

const scan = dir => { ... } // assigns array of files to tree

const upload = file => {
    const stream = fs.createReadStream(file) 
    stream.on('data', async chunk => {
        stream.pause()
        try {
            let response = await fetch('https://some/endpoint', {
                method: 'post',
                body: JSON.stringify({
                    file: file,
                    chunk: chunk.toString('base64')
                }) 
            })
            stream.resume()
        } catch(e) {
            // handle errors
        }
    })
    stream.on('end', () => {
       console.log('end', file)
    })
    stream.on('error', err => {
        console.log('error', err)
    })
}


仅供参考:这个问题实际上不是关于async/await的,而是关于流的。那是一个非常专业化的主题。也许你可以考虑使用一个库来解决这个问题?有很多选择,比如 https://www.npmjs.com/package/formidable - user3658510
1
好吧,让库来完成繁重的工作并不能学到什么...但还是谢谢你的回复 :) - Bill Kervaski
1个回答

4

Array.prototype.forEach同步运行,直到处理完数组的所有元素,丢弃调用它的参数函数返回的任何值。

如果想一次上传一个文件,请尝试使用await(在异步函数内部)等待每个文件上传,同时从上传过程中返回一个promise,在上传完成时变为已实现状态。概念上(没有优雅的错误处理),它可能看起来像:

const uploadTree = async tree => {
    for( file of tree) {
         await uploadFile( file); // process files one at a time
    }
}

// wrap the existing upload code in a promise executor:

const uploadFile = file => new Promise( (resolve, reject) => {
     const stream = fs.createReadStream(file)
     stream.on('data' ...
        ...
     } catch(e) {
        console.log( "Error uploading chunk of %s", file)
        reject(e) // handle errors
     }
     stream.on('end', resolve)
     stream.on('error', e=> {
        console.log(" Error reading %s", file)
        reject (e)
     })
});

// upload complete tree array files:

uploadTree(tree)
.then( ()=> console.log( "tree uploaded successfully"));
.catch( err=> console.log("An upload failed: ", err));

1
谢谢!这不仅是一个优雅的解决方案,我还学到了东西。赞++ - Bill Kervaski

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接