サーチ…


備考

CollectionFSパッケージは執筆者によって棚上げされ、廃止されました。しかし、MongoのGridFS機能を使用するためのAtmosphereやMeteorエコシステムには別のパッケージがなく、コードはまだ完全にうまく動作しています。他のGridFSソリューションを置き換えてドキュメント化するまで、StackOverflowドキュメントからこの例を削除しないことをお勧めします。

その他の研究
Filepicker.ioアップロードとイメージ変換
Darioのファイルパターンの保存
Micha Roonのファイルアップロードパターン
EventedMindファイルアップロードパッケージ

サーバー/クライアント

ファイルをアップロードすることは、あなたがしたいことに応じて、簡単にも複雑にもなります。一般に、ファイル自体を転送することはそれほど難しいことではありません。しかし、添付ファイル、バイナリファイルなどの周りには多くのエッジケースがあります。実際のポイントは水平スケーリングであり、サーバーが2番目、3番目、およびn番目にクローンされたときに機能するソリューションを作成します。

基本的なサーバー/クライアントアップロードモデルから始めましょう。まずファイル入力要素をドキュメントオブジェクトモデルに追加します。

<template name="example">
  <input type=file />
</template>

その後、コントローラ内のinput要素にイベントをアタッチし、ローカルのMeteorメソッド `` startFileTransfer ''を呼び出して転送を開始します。

// client/example.js
Template.example.events({
  'change input': function(ev) {  
    _.each(ev.srcElement.files, function(file) {
      Meteor.startFileTransfer(file, file.name);
    });
  }
});

// client/save.js
/**
 * @blob (https://developer.mozilla.org/en-US/docs/DOM/Blob)
 * @name the file's name
 * @type the file's type: binary, text (https://developer.mozilla.org/en-US/docs/DOM/FileReader#Methods) 
 *
 * TODO Support other encodings: https://developer.mozilla.org/en-US/docs/DOM/FileReader#Methods
 * ArrayBuffer / DataURL (base64)
 */
Meteor.startFileTransfer = function(blob, name, path, type, callback) {
  var fileReader = new FileReader(),
    method, encoding = 'binary', type = type || 'binary';
  switch (type) {
    case 'text':
      // TODO Is this needed? If we're uploading content from file, yes, but if it's from an input/textarea I think not...
      method = 'readAsText';
      encoding = 'utf8';
      break;
    case 'binary': 
      method = 'readAsBinaryString';
      encoding = 'binary';
      break;
    default:
      method = 'readAsBinaryString';
      encoding = 'binary';
      break;
  }
  fileReader.onload = function(file) {
    Meteor.call('saveFileToDisk', file.srcElement.result, name, path, encoding, callback);
  }
  fileReader[method](blob);
}

クライアントはsaveFileToDiskサーバーメソッドを呼び出します。これは実際の転送を行い、すべてをディスクに格納します。

// 
/**
 * TODO support other encodings:
 * http://stackoverflow.com/questions/7329128/how-to-write-binary-data-to-a-file-using-node-js
 */
Meteor.methods({
  saveFileToDisk: function(blob, name, path, encoding) {
    var path = cleanPath(path), fs = __meteor_bootstrap__.require('fs'),
      name = cleanName(name || 'file'), encoding = encoding || 'binary',
      chroot = Meteor.chroot || 'public';
    // Clean up the path. Remove any initial and final '/' -we prefix them-,
    // any sort of attempt to go to the parent directory '..' and any empty directories in
    // between '/////' - which may happen after removing '..'
    path = chroot + (path ? '/' + path + '/' : '/');

    // TODO Add file existance checks, etc...
    fs.writeFile(path + name, blob, encoding, function(err) {
      if (err) {
        throw (new Meteor.Error(500, 'Failed to save file.', err));
      } else {
        console.log('The file ' + name + ' (' + encoding + ') was saved to ' + path);
      }
    }); 

    function cleanPath(str) {
      if (str) {
        return str.replace(/\.\./g,'').replace(/\/+/g,'').
          replace(/^\/+/,'').replace(/\/+$/,'');
      }
    }
    function cleanName(str) {
      return str.replace(/\.\./g,'').replace(/\//g,'');
    }
  }
});

それは裸の骨のアプローチのようなものです、そして、それは望むために多くを残します。 CSVファイルなどをアップロードすると良いかもしれませんが、それはそれです。

Dropzone(アイロン:ルータ付き)

Dropzone UIとRESTエンドポイントが統合された、もう少し洗練されたものが必要な場合は、UIヘルパーを使用してカスタムRESTルートとパッケージを追加する必要があります。

Iron RouterとDropzoneをインポートすることから始めましょう。

 meteor add iron:router
 meteor add awatson1978:dropzone

また、dropzoneヘルパーで指定されたアップロードURLルートを設定します。

Router.map(function () {
    this.route('uploads', {
      where: 'server',
      action: function () {
        var fs = Npm.require('fs');
        var path = Npm.require('path');
        var self = this;

        ROOT_APP_PATH = fs.realpathSync('.');

        // dropzone.js stores the uploaded file in the /tmp directory, which we access
        fs.readFile(self.request.files.file.path, function (err, data) {

          // and then write the file to the uploads directory
          fs.writeFile(ROOT_APP_PATH + "/assets/app/uploads/" +self.request.files.file.name, data, 'binary', function (error, result) {
            if(error){
              console.error(error);
            }
            if(result){
              console.log('Success! ', result);
            }
          });
        });
      }
    });
  });

クール!わかりやすいUIとプログラム可能なRESTエンドポイントを備えたファイルアップローダーがあります。残念ながら、これは特にうまく調整できません。

Filepicker.io

物事を拡大するには、サーバー上のローカルストレージの使用をやめ、専用のファイルストレージサービスの使用を開始するか、または水平ストレージレイヤーを実装する必要があります。スケーラブルなファイルストレージを使い始める最も簡単な方法は、S3、Azure、Rackspace、DropboxをサポートするFilepicker.ioのようなソリューションを使用することです。 loadpickerはしばらくの間、一般的なFilerpickerのユニパッケージでした。

meteor add mrt:filepicker

Filepickerパターンは、他のソリューションとはかなり異なっています。これは、実際にサードパーティの統合に関するものです。まず、filepicker入力を追加します。この入力は、meteorアプリケーションではあまり一般的ではないdata- *属性に大きく依存しています。

<input type="filepicker"
  id="filepickerAttachment"
  data-fp-button-class="btn filepickerAttachment"
  data-fp-button-text="Add image" 
  data-fp-mimetypes="image/*"
  data-fp-container="modal"
  data-fp-maxsize="5000000" 
  data-fp-services="COMPUTER,IMAGE_SEARCH,URL,DROPBOX,GITHUB,GOOGLE_DRIVE,GMAIL">

APIキーを設定し、ファイルピッカーウィジェットを構築し、トリガーし、その出力を観察したいと思うでしょう。

if(Meteor.isClient){
  Meteor.startup(function() {
    filepicker.setKey("YourFilepickerApiKey");
  });
  Template.yourTemplate.rendered = function(){
    filepicker.constructWidget($("#filepickerAttachment"));
  }
  Template.yourTemplate.events({
  'change #filepickerAttachment': function (evt) {
    console.log("Event: ", evt, evt.fpfile, "Generated image url:", evt.fpfile.url);
  });
});

CollectionFS

しかし、ストレージについて真剣に考えていて、何百万ものイメージを保存したい場合は、MongoのGridFSインフラストラクチャを活用して、自分自身をストレージレイヤーにする必要があります。そのためには、優れたCollectionFSサブシステムが必要になります。

まず、必要なパッケージを追加します。

meteor add cfs:standard-packages
meteor add cfs:filesystem

あなたのオブジェクトモデルにファイルアップロード要素を追加する。

<template name="yourTemplate">
    <input class="your-upload-class" type="file">
</template>

次に、クライアントにイベント・コントローラーを追加します。

Template.yourTemplate.events({
    'change .your-upload-class': function(event, template) {
        FS.Utility.eachFile(event, function(file) {
            var yourFile = new FS.File(file);
            yourFile.creatorId = Meteor.userId(); // add custom data
            YourFileCollection.insert(yourFile, function (err, fileObj) {
                if (!err) {
                   // do callback stuff
                }
            });
        });
    }
});

そしてあなたのコレクションをあなたのサーバー上で定義してください:

YourFileCollection = new FS.Collection("yourFileCollection", {
    stores: [new FS.Store.FileSystem("yourFileCollection", {path: "~/meteor_uploads"})]
});
YourFileCollection.allow({
    insert: function (userId, doc) {
        return !!userId;
    },
    update: function (userId, doc) {
        return doc.creatorId == userId
    },
    download: function (userId, doc) {
        return doc.creatorId == userId
    }
});

この優れた例のためにRazに感謝します。すべてのCollectionFSでできることの詳細については、完全なCollectionFSドキュメントを参照してください。

サーバーアップロード

次のスクリプトは、サーバーファイルシステムからサーバーにファイルをアップロードするためのスクリプトです。主に設定ファイルとファイルウォッチャーです。

//https://forums.meteor.com/t/read-file-from-the-public-folder/4910/5

// Asynchronous Method.
Meteor.startup(function () {
    console.log('starting up');

    var fs = Npm.require('fs');
    // file originally saved as public/data/taxa.csv
    fs.readFile(process.cwd() + '/../web.browser/app/data/taxa.csv', 'utf8', function (err, data) {
        if (err) {
            console.log('Error: ' + err);
            return;
        }

        data = JSON.parse(data);
        console.log(data);
    });
});


// Synchronous Method.
Meteor.startup(function () {
    var fs = Npm.require('fs');
    // file originally saved as public/data/taxa.csv
    var data = fs.readFileSync(process.cwd() + '/../web.browser/app/data/taxa.csv', 'utf8');

    if (Icd10.find().count() === 0) {
        Icd10.insert({
            date:  new Date(),
            data:  JSON.parse(data)
        });
    }
});


Meteor.methods({
  parseCsvFile:function (){
    console.log('parseCsvFile');

    var fs = Npm.require('fs');
    // file originally saved as public/data/taxa.csv
    var data = fs.readFileSync(process.cwd() + '/../web.browser/app/data/taxa.csv', 'utf8');
    console.log('data', data);
  }
});


Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow