2016-05-25 7 views
4

S3ファイルストレージをNodeJSアプリケーションに統合しようとしています。 This tutorialを直接にアップロードする方法を説明するのは非常に良いですが、自分のウェブアプリケーションのAPIを介してのみファイルにアクセスできるようにするため、私のニーズには適していません。私はS3のURLでファイルを公開したくないのですが、例えば/api/files/<user_id>/<item_id>/<filename>で利用できるようにしたいだけです。S3 URLを公開せずにAmazon S3からNodeJSサーバーにファイルを渡す?

私のAPIを経由してダウンロードするは、ユーザーがこの特定のファイルを表示することが許可されていることを確認できるようにするためです。これはそのMongoDBの_idプロパティと同じになるように、私は、ファイル名を割り当てるためにどの<item_id>知っているように、私はアップロードは私のサーバーを経由したい

理由があります。アイテムがMongo _idを最初に持っている前に、私がS3にファイルをアップロードすると、私はこれを行うことができません。

NodeJSアプリケーションを使用して、S3からクライアントへ、またはその逆にファイルをストリーミングする方法の簡単なチュートリアルが見つかりませんでした。あなたはS3 REST APIを使用することができます

答えて

8

エクスプレスミドルウェア(リクエストを行ったユーザーの承認を確認する)とNode AWS SDKの使用は、このトリックを行う必要があります。

アップロードにはmulterを使用した完全な例を示します。

var express = require('express'); 
var app = express(); 
var router = express.Router(); 
var multer = require('multer'); 
var upload = multer({ 
    dest: "tmp/" 
}); 
var fs = require('fs'); 
var async = require('async'); 
var AWS = require('aws-sdk'); 
// Configure AWS SDK here 
var s3 = new AWS.s3({ 
    params: { 
    Bucket: 'xxx' 
    } 
}); 

/** 
* Authentication middleware 
* 
* It will be called for any routes starting with /files 
*/ 
app.use("/files", function (req, res, next) { 
    var authorized = true; // use custom logic here 
    if (!authorized) { 
    return res.status(403).end("not authorized"); 
    } 
    next(); 
}); 

// Route for the upload 
app.post("/files/upload", upload.single("form-field-name"), function (req, res) { 
    var fileInfo = console.log(req.file); 
    var fileStream = fs.readFileSync(fileInfo.path); 
    var options = { 
    Bucket: 'xxx', 
    Key: 'yyy/'+fileName, 
    Body: fileStream 
    }; 

    s3.upload(options, function (err) { 
    // Remove the temporary file 
    fs.removeFileSync("tmp/"+fileInfo.path); // ideally use the async version 
    if (err) { 
     return res.status(500).end("Upload to s3 failed"); 
    } 
    res.status(200).end("File uploaded"); 
    }); 
}); 

// Route for the download 
app.get("/files/download/:name", function (req, res) { 
    var fileName = req.params.name; 
    if (!fileName) { 
    return res.status(400).end("missing file name"); 
    } 
    var options = { 
    Bucket: 'xxx', 
    Key: 'yyy/'+fileName 
    }; 
    res.attachment(fileName); 
    s3.getObject(options).createReadStream().pipe(res); 
}); 

app.listen(3000); 

明らかにこれは部分的にしかテストし、適切なエラー処理の欠けている - それがうまくいけば、それはあなたにそれを実装する方法の大まかなアイデアを与える必要があります。

+0

ありがとうございます!私はアップロードとダウンロードのための簡単なヘルパー関数を提供するs3ライブラリを使ってこれを始めることにしましたが、私はこの答えを他のものについて参考にします。 – Aron

+0

あなたは[node-s3-client](https://github.com/andrewrk/node-s3-client)を参照していますか?はいの場合、私はあなたに警告する必要があります、私はそれで非常に悪い経験をしてきました。例えば、[issue#127](https://github.com/andrewr/node-s3-client/issues/127)、[issue#121](https://github.com/andrewrk/node-s3-クライアント/問題/ 121) – christophetd

+0

ああ。はい、そうです。 Hmmm:/ OKプロトタイプフェーズではこれに固執しますが、フェーズ2では自分のやり方でやります。 – Aron

2

ありがとうございました。バケツのオブジェクトをバックエンドから直接GETまたはPUTするように署名されたリクエストを行うことができます。

原則はあなたのリンクに記載されているものと似ています。 バックエンドは、オブジェクトを操作するための署名付きURLを作成するためにAWS JS SDKを使用する必要があります。 ExpressルートのS3から何かをリクエストする前に、または必要なチェックを自由に行うことができます。

... 
[assume that you are in an express route with req/res objects] 
... 
var aws = require('aws-sdk'), 
    s3 = new aws.S3(); 

aws.config.region = 'your_region'; 
aws.config.credentials = { 
    accessKeyId: 'your_key', 
    secretAccessKey: 'your_secret' 
}; 

s3.getSignedUrl('getObject', {Bucket: 'your_bucket', Key: 'your_file_name', Expires: 3600}, function (error, url) { 
    if (error || !url) { 
    //error while creating the URL 
    res.status(500).end(); 
    } else { 
    //make a request to the signed URL to get the file and pipe the res to the client 
    request({ 
     url: url 
    }).pipe(res); 
    } 
}); 

あなたはhereアマゾンからのより多くの例があります:

は、ここで簡単なGETの例(それだけで主なアイデア、完全に機能していない)です。

関連する問題