【发布时间】:2019-05-07 21:44:47
【问题描述】:
上下文:我正在编写代码,该代码使用读取流从 SFTP 服务器下载文件并通过 writeStream 将其上传到 GCS,使用 Nodejs v10.15.3。
由于我正在使用的 SFTP 库中的错误,stream.pipe(即库产生的读取流中的管道)实际上在节点 10 中被破坏,因此,我正尝试上传此文件通过以下代码文件(其中stream 是读取流,省略了不必要的信息):
let acl = fileMode;
if (fileMode === 'public') {
// options for acl are publicRead and private
// need to add the Read if public
acl += 'Read';
}
var options = {
predefinedAcl: acl,
destination: destPath,
metadata: {
contentType: contentType,
cacheControl: 'no-cache'
}
};
// Add in a check here for if the bucket exists
let file = new File(bucket, destPath);
let writeStream = file.createWriteStream(options);
writeStream.on('finish', () => {
file.getMetadata()
.then((metadata) => {
console.log('metadata', metadata);
return resolve(metadata);
})
.catch(error => {
console.error('Error getting file metadata', error);
return reject(error);
});
});
stream.on('end', () => {
try {
writeStream.end();
} catch (err) {
console.error('Error closing writeStream', err);
return reject(err);
}
});
writeStream.on('error', error => {
console.error('Error in writeStream', error);
return reject(error);
});
stream.on('error', error => {
console.error('Error in stream', error);
return reject(error);
});
let data = stream.read();
while (data) {
writeStream.write(data);
data = stream.read();
}
当我使用 while (data) 方法从我们的 SFTP 服务器流式传输到文件系统上的本地文件时,这可以正常工作。但是,当我尝试运行此代码以上传到我们的 GCS 文件时,我收到以下错误:
MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 close listeners added. Use emitter.setMaxListeners() to increase limit
Error in writeStream Error: Retry limit exceeded
// stacktrace omitted
Error Uploading to GCS from a stream: Retry limit exceeded
Error: Retry limit exceeded
似乎我在这里一定做错了什么,但我不知道为什么这不是一个有效的方法,我也不确定我是否错过了一些微妙的流(我坦白承认这几乎是对我来说是黑匣子)或 GCS 的问题。
编辑:好的,这实际上似乎与 SFTP 问题完全无关。我尝试使用推荐的方法从本地 fs 上传文件,并且看到相同的错误。我正在尝试的更“简化”的代码是:
// Add in a check here for if the bucket exists
let file = new File(bucket, destPath);
fs.createReadStream('sample_file.csv')
.pipe(file.createWriteStream(options))
.on('error', function(err) {
console.error('err', err);
return reject(err);
})
.on('finish', function() {
console.log('resolving');
return resolve({gcsUrl: url});
});
【问题讨论】:
-
你在哪里运行你的代码?是 App Engine、Cloud Function、Cloud Run、Compute VM Instance 还是 Google Cloud 之外的服务器?
-
此错误:从流上传到 GCS:超出重试限制由客户端库升级:对于发生 5 次以上的错误 404 或当指数回退失败超过 5 次时从 499 到 600 .
-
现在它通过 Google Cloud 外部的本地 docker 设置运行,这是我们在部署服务之前在本地开发和测试服务的地方。
-
您是否为存储桶正确配置了 CORS?您是否将您的用户/服务帐户配置为对存储桶具有写入权限?您能否通过您使用的配置验证使用 gsutil(Could SDK)上传是否有效?
-
这三个问题的答案都应该是肯定的。值得注意的是
bucket.exists可以工作,等等。
标签: javascript node.js google-cloud-storage