NodeJSでAmazon S3へファイルをアップロードする
質問
S3 バケットにファイルをアップロードしようとしているときに問題にぶつかりました。私のファイル パラメータが適切でないように見えることを除いて、すべてが動作します。私は、nodejsからS3へのアップロードにAmazon S3 sdkを使用しています。
これらは私のルート設定です。
var multiparty = require('connect-multiparty'),
multipartyMiddleware = multiparty();
app.route('/api/items/upload').post(multipartyMiddleware, items.upload);
items.upload()関数です。
exports.upload = function(req, res) {
var file = req.files.file;
var s3bucket = new AWS.S3({params: {Bucket: 'mybucketname'}});
s3bucket.createBucket(function() {
var params = {
Key: file.name,
Body: file
};
s3bucket.upload(params, function(err, data) {
console.log("PRINT FILE:", file);
if (err) {
console.log('ERROR MSG: ', err);
} else {
console.log('Successfully uploaded data');
}
});
});
};
設定
Body
のような文字列を
"hello"
は正常に動作します。によると
doc
,
Body
param は
(Buffer, Typed Array, Blob, String, ReadableStream) オブジェクトデータを取ります。
しかし、ファイルオブジェクトのアップロードは以下のエラーメッセージが表示され、失敗します。
[Error: Unsupported body payload object]
これはファイルオブジェクトです。
{ fieldName: 'file',
originalFilename: 'second_fnp.png',
path: '/var/folders/ps/l8lvygws0w93trqz7yj1t5sr0000gn/T/26374-7ttwvc.png',
headers:
{ 'content-disposition': 'form-data; name="file"; filename="second_fnp.png"',
'content-type': 'image/png' },
ws:
{ _writableState:
{ highWaterMark: 16384,
objectMode: false,
needDrain: true,
ending: true,
ended: true,
finished: true,
decodeStrings: true,
defaultEncoding: 'utf8',
length: 0,
writing: false,
sync: false,
bufferProcessing: false,
onwrite: [Function],
writecb: null,
writelen: 0,
buffer: [],
errorEmitted: false },
writable: true,
domain: null,
_events: { error: [Object], close: [Object] },
_maxListeners: 10,
path: '/var/folders/ps/l8lvygws0w93trqz7yj1t5sr0000gn/T/26374-7ttwvc.png',
fd: null,
flags: 'w',
mode: 438,
start: undefined,
pos: undefined,
bytesWritten: 261937,
closed: true },
size: 261937,
name: 'second_fnp.png',
type: 'image/png' }
どんな助けでも大歓迎です!
どのように解決するのですか?
ここでは、いくつかのことがうまくいっていないようです。あなたの投稿に基づくと、ファイル アップロードをサポートしようとしているように見えます。
connect-multiparty
ミドルウェアを使用しています。このミドルウェアが行うことは、アップロードされたファイルを受け取り、それをローカルのファイルシステムに書き込んで、それから
req.files
をアップロードされたファイルに設定します。
ルートの設定は問題ないようです。
items.upload()
関数にあるようです。特にこの部分です。
var params = {
Key: file.name,
Body: file
};
回答の冒頭で述べたように
connect-multiparty
はローカルファイルシステムにファイルを書き込むので、ファイルを開いて読み、アップロードし、ローカルファイルシステムで削除する必要があります。
つまり、次のようなメソッドに更新することができます。
var fs = require('fs');
exports.upload = function (req, res) {
var file = req.files.file;
fs.readFile(file.path, function (err, data) {
if (err) throw err; // Something went wrong!
var s3bucket = new AWS.S3({params: {Bucket: 'mybucketname'}});
s3bucket.createBucket(function () {
var params = {
Key: file.originalFilename, //file.name doesn't exist as a property
Body: data
};
s3bucket.upload(params, function (err, data) {
// Whether there is an error or not, delete the temp file
fs.unlink(file.path, function (err) {
if (err) {
console.error(err);
}
console.log('Temp File Delete');
});
console.log("PRINT FILE:", file);
if (err) {
console.log('ERROR MSG: ', err);
res.status(500).send(err);
} else {
console.log('Successfully uploaded data');
res.status(200).end();
}
});
});
});
};
これは何をするかというと、アップロードされたファイルをローカルファイルシステムから読み込んで、S3にアップロードし、一時ファイルを削除してレスポンスを送信するのです。
この方法にはいくつかの問題があります。まず、大きなファイルでは、書き込む前にファイル全体を読み込むことになるので、効率的ではありません。第二に、このプロセスは、大きなファイルのマルチパート アップロードをサポートしていません (マルチパート アップロードを行う前のカットオフ値は 5 Mb だと思います)。
代わりに私が提案したいのは、私が取り組んでいる S3FS これはネイティブの FS に似たインターフェースを提供しますが、マルチパートアップロードや S3 API などの詳細は抽象化されています(再帰的メソッドなどの追加機能もあります)。
もし、あなたが S3FS ライブラリを引っ張ってくるとしたら、コードは次のようになります。
var fs = require('fs'),
S3FS = require('s3fs'),
s3fsImpl = new S3FS('mybucketname', {
accessKeyId: XXXXXXXXXXX,
secretAccessKey: XXXXXXXXXXXXXXXXX
});
// Create our bucket if it doesn't exist
s3fsImpl.create();
exports.upload = function (req, res) {
var file = req.files.file;
var stream = fs.createReadStream(file.path);
return s3fsImpl.writeFile(file.originalFilename, stream).then(function () {
fs.unlink(file.path, function (err) {
if (err) {
console.error(err);
}
});
res.status(200).end();
});
};
これは、提供されたバケットと AWS 認証情報に対してモジュールをインスタンス化し、バケットが存在しない場合は作成するものです。そして、ファイルをアップロードするためのリクエストが来たときに、ファイルへのストリームを開き、それを使って指定したパスに S3 にファイルを書き込みます。これは、(必要であれば)舞台裏でマルチパートのアップロード部分を処理し、ストリームを通じて行われるという利点があるので、アップロードを開始する前にファイル全体を読み込むために待つ必要はありません。
お望みであれば、このコードを プロミス . あるいは pipe() メソッドをイベントリスナーで使用して、終了/エラーを判断することもできます。
もし、いくつかの追加のメソッドを探しているのであれば、s3fsのドキュメントをチェックしてください。
関連
-
[解決済み】エラーです。EACCES: 権限が拒否されました、アクセス '/usr/local/lib/node_modules' 。
-
[解決済み] 非推奨パッケージに関するNPM警告メッセージ
-
[解決済み】Node.jsのホスト名/IPが証明書のaltnamesと一致しない。
-
[解決済み】npm 5で作成されたpackage-lock.jsonファイルはコミットするのでしょうか?
-
[解決済み】POSTできない/expressを使用するとエラーが発生する
-
[解決済み] npm install エラー - ローカルの発行者証明書を取得できません。
-
[解決済み] Heroku "状態が起動から停止に変更されました SIGTERMで全プロセスを停止"
-
[解決済み] npm package.jsonファイルのdependencies, devDependencies, peerDependenciesの違いは何ですか?
-
[解決済み] forEachループでasync/awaitを使用する
-
[解決済み] Node.jsでファイル/ディレクトリが存在するかどうかを同期的にチェックする
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] リソースの読み込みに失敗しました: net::ERR_CONNECTION_REFUSED : Nodejs
-
[解決済み】ExpressJSとMeteorJSの比較【終了しました
-
[解決済み】"npm update -g" の後に "Cannot find module 'npmlog'" というエラーが発生する。
-
[解決済み】ENOENT, そのようなファイルまたはディレクトリがありません。
-
[解決済み】passport.js passport.initialize() ミドルウェアが使用されていません。
-
[解決済み] AWS s3 api error: specified bucket does not exist.
-
[解決済み] のエラーが発生しました。これはおそらくnpmの問題ではありません。上に追加のログ出力があると思われます
-
[解決済み] http-server コマンドが見つかりません。
-
[解決済み] バルク更新を行う。
-
[解決済み] Macでポート3000をロックしているプロセスを見つける(そして殺す)【終了