无法将s3对象readstream传递给PUT请求

我有一个简单的情况。 我需要从S3中读取一个对象,并将其输出传递给PUT请求。 这是我的代码使用请求 。

 // client.js let AWS = require('aws-sdk') let request = require('request') let bucket = 'my_bucket' let filename = 'path/to/file.zip' let host = 'localhost' let port = 8080 let s3 = new AWS.S3({ . . . }) let readStream = s3.getObject({ Bucket: bucket, Key: filename }).createReadStream() let formData = { applicationType: 'my_app_type', applicationName: 'my_app_name', upload: { value: readStream, options: { filename: 'my_file_name.zip', contentType: 'application/zip' } } } request.put({ url: 'http://' + host + ':' + port + '/bootstrap', formData: formData }, function (error, response, body) { if (error) throw error console.log(body) }) 

而且,这是我的server.js代码。

 // server.js let http = require('http') let Busboy = require('busboy') let events = require('events') let fs = require('fs') let host = 'localhost' let port = 8080 let compressedCodeLocation = './code.zip' let handleRequest = function (request, response) { let eventEmitter = new events.EventEmitter() let inputStreamWriter = fs.createWriteStream(compressedCodeLocation) inputStreamWriter.on('finish', function () { eventEmitter.emit('input.stream.saved') }) let busboy = new Busboy({ headers: request.headers }) busboy.on('file', function (field, file) { file.pipe(inputStreamWriter) }) busboy.on('field', function (field, val) { console.log(field + ': ' + val) }) eventEmitter.on('input.stream.saved', function () { let stats = fs.statSync(compressedCodeLocation) response.statusCode = 200 response.end(JSON.stringify(stats)) }) request.pipe(busboy) } let server = http.createServer(handleRequest) server.listen(port, host, function () { console.log('Server started on ' + host + ':' + port) }) let handleShutdown = function () { server.close(function () { console.log('Server stopped on ' + host + ':' + port) }) } process.on('SIGTERM', handleShutdown) process.on('SIGINT', handleShutdown) 

Server收到以下headers

 { host: 'localhost:8080', 'content-type': 'multipart/form-data; boundary=--------------------------870259812928253745629174', 'content-length': '465', connection: 'close' } 

我在Server端收到这个错误:

 File [upload] got 58 bytes events.js:160 throw er; // Unhandled 'error' event ^ Error: Unexpected end of multipart data at /pots/cnc/node_modules/dicer/lib/Dicer.js:62:28 at _combinedTickCallback (internal/process/next_tick.js:67:7) at process._tickCallback (internal/process/next_tick.js:98:9) 

而且, Client收到以下错误:

 Error: read ECONNRESET at exports._errnoException (util.js:1018:11) at TCP.onread (net.js:568:26) 

有趣的是,如果我先保存文件本地,然后createReadStream本地文件,它的工作原理:

 let formData = { ... upload: { value: fs.createReadStream(localPath + "/" + filename), options: { ... } } }; 

我无法使用请求。 但工作得很好。 尝试这个:

 const {S3} = require('aws-sdk'), got = require('got'), FormData = require('form-data'), ; const form = new FormData(), readStream = s3.getObject({ Bucket: bucket, Key: filename }).createReadStream() ; form.append('applicationType', 'my_app_type') form.append('applicationName', 'my_app_name') form.append('upload', readStream,{ filename: 'my_file_name.zip', contentType: 'application/zip' }) got.put('http://' + host + ':' + port + '/bootstrap', {body: form}) 

此解决scheme正在使用请求模块本身,以防您 不想将新库引入您的代码。

我用@metakungfu的答案解决了这个问题。 请将任何投票redirect到他的答案。

我需要将require模块的窗体重置为form-data模块的窗体。 正如request 文件所述:

对于高级的情况,你可以通过r.form()来访问表单数据对象本身。

一旦我的请求(我认为重写多部分边界)中设置了新表单,我将表单数据传送给我的请求。 请参阅参考 。

 let AWS = require('aws-sdk') let FormData = require('form-data') let request = require('request') let bucket = 'ppi-uploads' let filename = 'introduction.zip' let host = 'localhost' let port = 8080 let s3 = new AWS.S3({ . . . }) let readStream = s3.getObject({ Bucket: bucket, Key: filename }).createReadStream() let form = new FormData() form.append('applicationType', 'html') form.append('applicationName', 'introduction') form.append('upload', readStream, { filename: 'introduction.zip', contentType: 'application/zip' }) let putRequest = request.put({ url: 'http://' + host + ':' + port + '/bootstrap', headers: form.getHeaders() }, function (error, response, body) { if (error) throw error console.log(body) }) form.pipe(putRequest)