diff --git a/.versions b/.versions index 299bbd48..47f7011f 100644 --- a/.versions +++ b/.versions @@ -26,7 +26,7 @@ modules-runtime@0.6.4_1 mongo-id@1.0.5 observe-sequence@1.0.12 ostrio:cookies@2.0.4 -ostrio:files@1.6.1 +ostrio:files@1.6.2 promise@0.7.2_1 random@1.0.10 reactive-var@1.0.10 diff --git a/README.md b/README.md index 584d6ce1..52f41cea 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,10 @@ +[![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=FVDSXRFW9VGA2) +[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/VeliovGroup/Meteor-Files) +[![GitHub issues](https://img.shields.io/github/issues/VeliovGroup/Meteor-Files.svg)](https://github.com/VeliovGroup/Meteor-Files/issues) +[![GitHub forks](https://img.shields.io/github/forks/VeliovGroup/Meteor-Files.svg)](https://github.com/VeliovGroup/Meteor-Files/network) +[![GitHub stars](https://img.shields.io/github/stars/VeliovGroup/Meteor-Files.svg)](https://github.com/VeliovGroup/Meteor-Files/stargazers) +[![Twitter](https://img.shields.io/twitter/url/https/github.com/VeliovGroup/Meteor-Files.svg?style=social)](https://twitter.com/intent/tweet?url=https%3A%2F%2Fgithub.com%2FVeliovGroup%2FMeteor-Files) + Files for Meteor ======== Extremely fast and robust package for file uploading, managing and streaming (*Audio & Video & Images*), with support of server's file system (FS) or third party storage, like: *AWS*, *DropBox*, *Google Storage*, *Google Drive*, *GridFS* or any other with API. @@ -8,11 +15,18 @@ For current upload *pause/continue*, *speed*, *remaining time* and *progress* se Support: ======== - - [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/VeliovGroup/Meteor-Files) + - [Ask a question via Gitter chat](https://gitter.im/VeliovGroup/Meteor-Files) - [Ask a question or submit an issue](https://github.com/VeliovGroup/Meteor-Files/issues) - [Releases / Changelog / History](https://github.com/VeliovGroup/Meteor-Files/releases) - For more docs and examples [read wiki](https://github.com/VeliovGroup/Meteor-Files/wiki) +Support Meteor-Files project: +======== + - [Donate via PayPal](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=FVDSXRFW9VGA2) + - Star on [GitHub](https://github.com/VeliovGroup/Meteor-Files) + - Stat on [Atmosphere](https://atmospherejs.com/ostrio/files) + - Share on [Facebook](https://www.facebook.com/sharer.php?u=https%3A%2F%2Fgithub.com%2FVeliovGroup%2FMeteor-Files) and [Twitter](https://twitter.com/share?url=https%3A%2F%2Fgithub.com%2FVeliovGroup%2FMeteor-Files) + Awards: ======== @@ -54,6 +68,8 @@ meteor add ostrio:files API overview (*[full API](https://github.com/VeliovGroup/Meteor-Files/wiki)*) ======== +Note: When using any of `accounts` packages - package `accounts-base` must be explicitly added to `.meteor/packages` above `ostrio:files` + #### `new FilesCollection([config])` [*Isomorphic*] Read full docs for [`FilesCollection` Constructor](https://github.com/VeliovGroup/Meteor-Files/wiki/Constructor) @@ -254,7 +270,7 @@ For more expressive example see [Download demo](https://github.com/VeliovGroup/M Supporters: ======== -Big thanks to all supporters. *Only because of this guys this project can have 100% of our attention*. +I would like to thank everyone who support this project. *Because of those guys this project can have 100% of our attention*. - [@themeteorchef](https://github.com/themeteorchef) - [@MeDBejoHok](https://github.com/medbejohok) @@ -262,4 +278,4 @@ Big thanks to all supporters. *Only because of this guys this project can have 1 | Meteor-Files | Expressive package to manage files within Meteor | |:-------------:|:------------- | -| [![logo](https://raw.githubusercontent.com/VeliovGroup/Meteor-Files/master/logo.png)](https://github.com/VeliovGroup/Meteor-Files) | If you found this package useful, please do not hesitate to star it at both [GitHub](https://github.com/VeliovGroup/Meteor-Files) and [Atmosphere](https://atmospherejs.com/ostrio/files). Also you may like to [Tweet](https://twitter.com/share?url=https%3A%2F%2Fgithub.com%2FVeliovGroup%2FMeteor-Files&text=File%20upload%20and%20delivery%20in%20Meteorjs%20-%20now%20it's%20easy!) about it or share at [Facebook](https://www.facebook.com/sharer.php?u=https%3A%2F%2Fgithub.com%2FVeliovGroup%2FMeteor-Files) | \ No newline at end of file +| [![logo](https://raw.githubusercontent.com/VeliovGroup/Meteor-Files/master/logo-bw.png)](https://github.com/VeliovGroup/Meteor-Files) | If you found this package useful, please do not hesitate to star it at both [GitHub](https://github.com/VeliovGroup/Meteor-Files) and [Atmosphere](https://atmospherejs.com/ostrio/files). Also you may like to [Tweet](https://twitter.com/share?url=https%3A%2F%2Fgithub.com%2FVeliovGroup%2FMeteor-Files&text=File%20upload%20and%20delivery%20in%20Meteorjs%20-%20now%20it's%20easy!) about it or share at [Facebook](https://www.facebook.com/sharer.php?u=https%3A%2F%2Fgithub.com%2FVeliovGroup%2FMeteor-Files)
[![Donate](https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=FVDSXRFW9VGA2) | \ No newline at end of file diff --git a/demo-simplest-download-button/.meteor/versions b/demo-simplest-download-button/.meteor/versions index 1d07d958..8504e775 100644 --- a/demo-simplest-download-button/.meteor/versions +++ b/demo-simplest-download-button/.meteor/versions @@ -55,7 +55,7 @@ npm-mongo@1.4.44_1 observe-sequence@1.0.12 ordered-dict@1.0.8 ostrio:cookies@2.0.4 -ostrio:files@1.6.0 +ostrio:files@1.6.2 promise@0.7.2_1 raix:eventemitter@0.1.3 random@1.0.10 diff --git a/demo-simplest-streaming/.meteor/versions b/demo-simplest-streaming/.meteor/versions index 4515c410..1300f9b0 100644 --- a/demo-simplest-streaming/.meteor/versions +++ b/demo-simplest-streaming/.meteor/versions @@ -49,7 +49,7 @@ npm-mongo@1.4.44_1 observe-sequence@1.0.12 ordered-dict@1.0.8 ostrio:cookies@2.0.4 -ostrio:files@1.6.0 +ostrio:files@1.6.2 promise@0.7.2_1 random@1.0.10 reactive-var@1.0.10 diff --git a/demo-simplest-upload/.meteor/versions b/demo-simplest-upload/.meteor/versions index e4f31a6f..1cc34300 100644 --- a/demo-simplest-upload/.meteor/versions +++ b/demo-simplest-upload/.meteor/versions @@ -49,7 +49,7 @@ npm-mongo@1.4.44_1 observe-sequence@1.0.12 ordered-dict@1.0.8 ostrio:cookies@2.0.4 -ostrio:files@1.6.0 +ostrio:files@1.6.2 ostrio:templatehelpers@1.1.2 promise@0.7.2_1 random@1.0.10 diff --git a/demo/.meteor/versions b/demo/.meteor/versions index 5180210e..38f1fd48 100644 --- a/demo/.meteor/versions +++ b/demo/.meteor/versions @@ -67,7 +67,7 @@ mobile-experience@1.0.4 mobile-status-bar@1.0.12 modules@0.6.4 modules-runtime@0.6.4_1 -momentjs:moment@2.13.1 +momentjs:moment@2.14.1 mongo@1.1.9_1 mongo-id@1.0.5 mquandalle:jade@0.4.9 @@ -81,7 +81,7 @@ observe-sequence@1.0.12 ordered-dict@1.0.8 ostrio:cookies@2.0.4 ostrio:cstorage@2.0.5 -ostrio:files@1.6.0 +ostrio:files@1.6.2 ostrio:flow-router-extra@2.12.2 ostrio:flow-router-meta@1.1.1 ostrio:flow-router-title@2.1.1 diff --git a/demo/app.json b/demo/app.json index 7a00ebe1..8b00daee 100644 --- a/demo/app.json +++ b/demo/app.json @@ -1,6 +1,6 @@ { "name": "Meteor-Files-Demo", - "version": "1.6.1", + "version": "1.6.2", "description": "Demo application for ostrio:files package", "repository": "https://github.com/VeliovGroup/Meteor-Files-Demo", "website": "https://github.com/VeliovGroup/Meteor-Files-Demo", diff --git a/demo/client/file/file.coffee b/demo/client/file/file.coffee index 04aa83d2..d94fb326 100644 --- a/demo/client/file/file.coffee +++ b/demo/client/file/file.coffee @@ -9,21 +9,24 @@ Template.file.onCreated -> Template.file.onRendered -> @warning.set false @fetchedText.set false - if (@data.file.get('isText') or @data.file.get('isJSON')) - self = @ - HTTP.call 'GET', @data.file.link(), (error, resp) -> - self.showPreview.set true - if error - console.error error - else - if !~[500, 404, 400].indexOf resp.statusCode - if resp.content.length < 1024 * 64 - self.fetchedText.set resp.content - else - self.warning.set true - return + if @data.file.isText or @data.file.isJSON + if @data.file.size < 1024 * 64 + self = @ + HTTP.call 'GET', @data.file.link(), (error, resp) -> + self.showPreview.set true + if error + console.error error + else + if !~[500, 404, 400].indexOf resp.statusCode + if resp.content.length < 1024 * 64 + self.fetchedText.set resp.content + else + self.warning.set true + return + else + @warning.set true - else if @data.file.get('isImage') + else if @data.file.isImage self = @ img = new Image() img.onload = -> diff --git a/demo/client/styles/styles.sass b/demo/client/styles/styles.sass index 01306399..4a9785e0 100644 --- a/demo/client/styles/styles.sass +++ b/demo/client/styles/styles.sass @@ -389,11 +389,13 @@ h1, h2, h3, h4, h5, h6, div, form, table, p img filter: grayscale(0%) i.fa-github - color: #fff + color: #999999 i.fa-twitter - color: #00aced + color: #55acee i.fa-facebook-official color: #3b5998 + i.fa-paypal + color: #009cde .block-info color: $text-color @@ -670,6 +672,11 @@ button max-height: 50% max-width: 50% !important +input.info-img + height: 32px + width: auto + margin: 0px 5px + ._404 text-align: center padding: 15px diff --git a/demo/client/user-account/login.coffee b/demo/client/user-account/login.coffee index 97ac8223..ccdff447 100644 --- a/demo/client/user-account/login.coffee +++ b/demo/client/user-account/login.coffee @@ -1,14 +1,3 @@ -Template.login.onCreated -> - self = @ - @serviceConfiguration = new ReactiveVar {} - Meteor.call 'getServiceConfiguration', (error, serviceConfiguration) -> - if error - console.error error - else - self.serviceConfiguration.set serviceConfiguration - return - return - Template.login.onRendered -> window.IS_RENDERED = true return @@ -16,7 +5,7 @@ Template.login.onRendered -> Template.login.helpers unlist: -> _app.unlist.get() secured: -> _app.secured.get() - serviceConfiguration: -> Template.instance().serviceConfiguration.get() + serviceConfiguration: -> _app.serviceConfiguration.get() Template.login.events 'click [data-login-meteor]': (e) -> diff --git a/demo/lib/__compatability/__globals.coffee b/demo/lib/__compatability/__globals.coffee index 67cec723..2f82c50b 100644 --- a/demo/lib/__compatability/__globals.coffee +++ b/demo/lib/__compatability/__globals.coffee @@ -19,6 +19,14 @@ if Meteor.isClient _app.currentUrl = -> Meteor.absoluteUrl((FlowRouter.current().path or document.location.pathname).replace(/^\//g, '')).split('?')[0].split('#')[0].replace '!', '' _app.storeTTLUser = 432000000 _app.showProjectInfo = new ReactiveVar false + + _app.serviceConfiguration = new ReactiveVar {} + Meteor.call 'getServiceConfiguration', (error, serviceConfiguration) -> + if error + console.error error + else + _app.serviceConfiguration.set serviceConfiguration + return Meteor.autorun -> ClientStorage.set 'blamed', _app.blamed.get() diff --git a/demo/package.json b/demo/package.json index 4820cb9f..6323e907 100644 --- a/demo/package.json +++ b/demo/package.json @@ -1,6 +1,6 @@ { "name": "Meteor-Files-Demo", - "version": "1.6.1", + "version": "1.6.2", "description": "Demo application for ostrio:files package", "main": "main.js", "scripts": { diff --git a/files.coffee b/files.coffee index fd438205..2a7edfc5 100755 --- a/files.coffee +++ b/files.coffee @@ -23,7 +23,7 @@ if Meteor.isServer @param path {String} - Path to file on FS @param maxLength {Number} - Max amount of chunks in stream @param file {Object} - fileRef Object - @summary writableStream wrapper class, makes sure chunks is written in given order + @summary writableStream wrapper class, makes sure chunks is written in given order. Implementation of queue stream. ### class writeStream constructor: (@path, @maxLength, @file) -> @@ -66,7 +66,7 @@ if Meteor.isServer @memberOf writeStream @name end @param {Function} callback - Callback - @summary Write chunk in given order + @summary Finishes writing to writableStream, only after all chunks in queue is written @returns {Boolean} - True if stream is fulfilled, false if queue is in progress ### end: (callback) -> @@ -484,7 +484,7 @@ class FilesCollection delete @interceptDownload delete @continueUploadTTL - if _.has(Package, 'accounts-base') and Accounts + if _.has(Package, 'accounts-base') setTokenCookie = -> if (not cookie.has('meteor_login_token') and Accounts._lastLoginTokenWhenPolled) or (cookie.has('meteor_login_token') and (cookie.get('meteor_login_token') isnt Accounts._lastLoginTokenWhenPolled)) cookie.set 'meteor_login_token', Accounts._lastLoginTokenWhenPolled, null, '/' @@ -525,14 +525,14 @@ class FilesCollection if @public and not storagePath throw new Meteor.Error 500, "[FilesCollection.#{@collectionName}] \"storagePath\" must be set on \"public\" collections! Note: \"storagePath\" must be equal on be inside of your web/proxy-server (absolute) root." - storagePath ?= "assets/app/uploads/#{@collectionName}" + storagePath ?= "assets#{nodePath.sep}app#{nodePath.sep}uploads#{nodePath.sep}#{@collectionName}" Object.defineProperty self, 'storagePath', { get: -> sp = '' if _.isString storagePath sp = storagePath else if _.isFunction storagePath - sp = storagePath.call self, "assets/app/uploads/#{self.collectionName}" + sp = storagePath.call self, "assets#{nodePath.sep}app#{nodePath.sep}uploads#{nodePath.sep}#{self.collectionName}" unless _.isString sp throw new Meteor.Error 400, "[FilesCollection.#{self.collectionName}] \"storagePath\" function must return a String!" @@ -888,7 +888,7 @@ class FilesCollection {extension, extensionWithDot} = @_getExt fileName result = opts.file - result.path = "#{@storagePath}/#{opts.FSName}#{extensionWithDot}" + result.path = "#{@storagePath}#{nodePath.sep}#{opts.FSName}#{extensionWithDot}" result.name = fileName result.meta = opts.file.meta result.extension = extension @@ -1024,13 +1024,13 @@ class FilesCollection if Meteor.isServer if http cookie = http.request.Cookies - if _.has(Package, 'accounts-base') and Accounts and cookie.has 'meteor_login_token' + if _.has(Package, 'accounts-base') and cookie.has 'meteor_login_token' user = Meteor.users.findOne 'services.resume.loginTokens.hashedToken': Accounts._hashLoginToken cookie.get 'meteor_login_token' if user result.user = () -> return user result.userId = user._id else - if _.has(Package, 'accounts-base') and Accounts and Meteor.userId() + if _.has(Package, 'accounts-base') and Meteor.userId() result.user = -> return Meteor.user() result.userId = Meteor.userId() @@ -1115,7 +1115,7 @@ class FilesCollection self = @ opts ?= {} - opts.path = "#{@storagePath}/#{FSName}#{extensionWithDot}" + opts.path = "#{@storagePath}#{nodePath.sep}#{FSName}#{extensionWithDot}" opts.type = @_getMimeType opts opts.meta ?= {} opts.size ?= buffer.length @@ -1179,7 +1179,7 @@ class FilesCollection {extension, extensionWithDot} = @_getExt fileName opts.meta ?= {} - opts.path = "#{@storagePath}/#{FSName}#{extensionWithDot}" + opts.path = "#{@storagePath}#{nodePath.sep}#{FSName}#{extensionWithDot}" storeResult = (result, callback) -> result._id = fileId @@ -1274,7 +1274,7 @@ class FilesCollection type: opts.type size: opts.size extension: extension - _storagePath: path.replace "/#{fileName}", '' + _storagePath: path.replace "#{nodePath.sep}#{fileName}", '' result._id = Random.id() @@ -1778,9 +1778,9 @@ class FilesCollection @summary Remove documents from the collection @returns {FilesCollection} Instance ### - remove: (selector, callback) -> + remove: (selector = {}, callback) -> console.info "[FilesCollection] [remove(#{JSON.stringify(selector)})]" if @debug - check selector, Match.Optional Match.OneOf Object, String + check selector, Match.OneOf Object, String check callback, Match.Optional Function if Meteor.isClient @@ -1823,16 +1823,25 @@ class FilesCollection @locus Server @memberOf FilesCollection @name deny - @name allow @param {Object} rules - @see http://docs.meteor.com/#/full/allow - @summary link Mongo.Collection allow/deny methods + @see https://docs.meteor.com/api/collections.html#Mongo-Collection-deny + @summary link Mongo.Collection deny methods @returns {Mongo.Collection} Instance ### deny: if Meteor.isServer then (rules) -> @collection.deny rules return @collection else undefined + + ### + @locus Server + @memberOf FilesCollection + @name allow + @param {Object} rules + @see https://docs.meteor.com/api/collections.html#Mongo-Collection-allow + @summary link Mongo.Collection allow methods + @returns {Mongo.Collection} Instance + ### allow: if Meteor.isServer then (rules) -> @collection.allow rules return @collection @@ -1842,9 +1851,8 @@ class FilesCollection @locus Server @memberOf FilesCollection @name denyClient - @name allowClient - @see http://docs.meteor.com/#/full/allow - @summary Shorthands for Mongo.Collection allow/deny methods + @see https://docs.meteor.com/api/collections.html#Mongo-Collection-deny + @summary Shorthands for Mongo.Collection deny method @returns {Mongo.Collection} Instance ### denyClient: if Meteor.isServer then -> @@ -1854,6 +1862,15 @@ class FilesCollection remove: -> true return @collection else undefined + + ### + @locus Server + @memberOf FilesCollection + @name allowClient + @see https://docs.meteor.com/api/collections.html#Mongo-Collection-allow + @summary Shorthands for Mongo.Collection allow method + @returns {Mongo.Collection} Instance + ### allowClient: if Meteor.isServer then -> @collection.allow insert: -> true @@ -1881,7 +1898,9 @@ class FilesCollection if fileRef.versions and not _.isEmpty fileRef.versions _.each fileRef.versions, (vRef) -> bound -> fs.unlink vRef.path, NOOP - fs.unlink fileRef.path, NOOP + return + else + fs.unlink fileRef.path, NOOP return @ else undefined diff --git a/package.js b/package.js index 928fa40a..9b7c8b79 100755 --- a/package.js +++ b/package.js @@ -1,7 +1,7 @@ Package.describe({ name: 'ostrio:files', - version: '1.6.1', - summary: 'Fast and robust file uploads and streaming (Audio & Video), support FS or AWS, DropBox, Google Drive', + version: '1.6.2', + summary: 'Fast and robust file upload package, with support of FS, AWS, GridFS, DropBox or Google Drive', git: 'https://github.com/VeliovGroup/Meteor-Files', documentation: 'README.md' });