Giter Club home page Giter Club logo

meteor-uploads's Introduction

News

  • 09/08/2019 - Update the DEMO application to Meteor 1.8.1
  • 18/11/2015 - Yet another batch of bugfixes, this time concerning exception and validation handling.
  • 2/10/2015 - Community is on fire! With their help, many new improvements are being included, such as dynamic from data.
  • 29/6/2015 - Bugfixes, localisation
  • 27/2/2015 - Validation of files on Client and Server (see section Validation)
  • 26/2/2015 - Custom built templates
  • 21/2/2015 - File caching now supported, configuration of mimeTypes to serve
  • 18/2/2015 - Full support for Cordova!
  • 23/1/2015:
    • Full support for Semantic UI
    • Breaking change in 'getFileInfo', 'getDirectory' and 'finished' callbacks, which is now passing fileInfo object instead of just a file name and folder. See documentation.
    • Possibility to automatically create directories on server
    • Possibility to delete files on server with UploadServer.delete(path), see DEMO
    • Possibility to easily modify the looks of the upload component or even add new upload templates for various frameworks by modifying the Uploader.UI. classes
    • Several bug fixes
    • Update the DEMO application to showcase all current possibilities
  • 1/12/2014 Now with drag and drop support!!!

Introduction

WARNING If you plan to deploy your solution to free *.meteor.com servers, this solution is not for you, since you have no write access outside of standard Meteor directories. Please use CollectionFS instead.

WARNING if you are submitting an issue on this website, please always use JavaScript. I do not use Coffee, nor anything else and it's just not polite.

These packages allow you to easily setup a file upload service to your Meteor server. This solution has following perks:

  1. Uses the famous jQuery file upload system from blueimp.
    1. As a result you can upload any file size (default limit 11GB)
    2. Displays upload progress
    3. Uploads can be canceled
    4. You can upload multiple files
    5. Images can be resized to various sizes using the imagemagick
  2. NEW! Support for Semantic UI!
  3. NEW! You can use drag and drop to upload your files!
  4. Saves and serves file from arbitrary folder on your server. This solves problems with hot-code reload, when files are saved into Meteor's public directory
    1. Possibility to save files to subfolders
    2. Possibility to rename files on the server
  5. Simple configuration and installation! No need to install 10+ packages like with Collection-FS solution

Please note that since we are using blueimp's juery solution, this solution has a full potential of performing client image resizes, chunked uploads, upload resume and more. These features will be gradually added. Pull requests are welcome!

For all the screen-shots, please scroll to the bottom of the page.

Quick Start

Install packages

$ meteor add tomi:upload-server
$ meteor add tomi:upload-jquery

Meteor Icon Meteor Icon

Install ImageMagick (if you plan to use image resizing)

If you want to use Imagemagick, follow these install instructions on your server. Then install node tools for imagemagick.

npm install -g imagemagick

Create directory in the application root

mkdir -p .uploads/tmp

Configure server

//file:/server/init.js
Meteor.startup(function () {
  UploadServer.init({
    tmpDir: process.env.PWD + '/.uploads/tmp',
    uploadDir: process.env.PWD + '/.uploads/',
    checkCreateDirectories: true //create the directories for you
  });
});

Configure client (only necessary if deploying as a Cordova app)

//file:/client/init.js
Meteor.startup(function() {
  Uploader.uploadUrl = Meteor.absoluteUrl("upload"); // Cordova needs absolute URL
});

Use template with bootstrap or semantic UI support

<template name="yourTemplate">
	{{> upload_bootstrap }}
</template>
<template name="yourTemplate">
	{{> upload_semanticUI }}
</template>

DONE!

You can also use the drag and drop zone!

<template name="yourTemplate">
	{{> dropzone }}
</template>

If you are using dropzone, you may want to set-up some css styles to give your user some visual cues:

.jqDropZone {
    background: lightgrey;
    width: 150px;
    height: 50px;
    line-height: 50px;
    text-align: center;
    font-weight: bold;
}
.jqDropZone.in {
    width: 600px;
    height: 200px;
    line-height: 200px;
    font-size: larger;
}
.jqDropZone.hover {
    background: lawngreen;
}
.jqDropZone.fade {
    -webkit-transition: all 0.3s ease-out;
    -moz-transition: all 0.3s ease-out;
    -ms-transition: all 0.3s ease-out;
    -o-transition: all 0.3s ease-out;
    transition: all 0.3s ease-out;
    opacity: 1;
}

Deploying with MUP or MUPX?

Mup deployments need no special attention, just make sure that the target upload directory has sufficient priviledges. For MUPX, please follow this thread (#235) for instructions on how to setup MUPX.

Installation

The installation is very simple and consists of installing two packages:

$ meteor add tomi:upload-server
$ meteor add tomi:upload-jquery

I have separated these two packages, because often you will want to run your upload service as a separate application. There are several options supported by blueimp, such as Java, ASP, Ruby and more or even node.js Express server installed via NPM. If you wish to use self standing server, install only the tomi:upload-jquery package.

Configuration

Server

First, we need to initialise the server and configure upload paths. We also allow server to create directories for us:

//file:/server/init.js
Meteor.startup(function () {
  UploadServer.init({
    tmpDir: '/Users/tomi/Documents/Uploads/tmp',
    uploadDir: '/Users/tomi/Documents/Uploads/',
    checkCreateDirectories: true,
    getDirectory: function(fileInfo, formData) {
      // create a sub-directory in the uploadDir based on the content type (e.g. 'images')
      return formData.contentType;
    },
    finished: function(fileInfo, formFields) {
      // perform a disk operation
    },
    cacheTime: 100,
    mimeTypes: {
        "xml": "application/xml",
        "vcf": "text/x-vcard"
    }
  });
});

Following options are available for UploadServer.init(options):

Field Type Default Description
tmpDir String null Temporary upload directory
checkCreateDirectories Boolean false Creates the upload and tmp directory if it does not exist
uploadDir String null Path to the upload directory
uploadUrl String '/upload/' Upload route
validateRequest function function(request) - Warning - Does not run in fibre, you have no access to collections
validateFile function function(fileInfo) - Warning - Does not run in fibre, you have no access to collections
maxPostSize int 11000000000 Maximum post size (11 GB)
minFileSize int 1 Minimum file size
maxFileSize int 10000000000 Maximum file size (10 GB)
overwrite Boolean false overwrites existing file, rather than adds numerical suffix
acceptFileTypes RegEx /.+/i, Accepted types of files (e.g. prohibit .exe)
imageTypes RegEx /\.(gif|jpe?g|png)$/i Images which can be resized with Imagemagick
imageVersions Object {} Defines the sizes of images which will be converted and saved to upload directory. For example {thumbnailBig: {width: 400, height: 300}, thumbnailSmall: {width: 200, height: 100}}
crop Boolean false Crops the image rather than resizes
getDirectory function functions which decides the subdirectory in which the file will be saved. If this function is not defined, no sub-directory is created. For example: function(fileInfo, formData) { return '/my/sub/directory'; }
getFileName function Renames the file on the server. If no function is specified, file is saved with the original file name. For example: function(fileInfo, formData) { return 'Saved-' + file.name; }
finished function Callback - You have full access to collections, but you do not have access to Meteor.userId() since upload process runs in its own fiber.
cacheTime int 86400 Cache time, set 0 to disable cache
mimeTypes Object see here List of available mime types
notFoundImage String null If set, this is the name of an image within uploadDir which will be served as a 404 image, instead of the default text error message. Default value of null will 404 with text/html only.

In callbacks we pass the fileInfo with the following structure:

Field Type Description
name String File name
size Number Size in Bytes
type String MIME file type (e.g. 'text/html')
path String Path relative to upload directory
url String Full url to the uploaded file

Passing data from server back to client

It is possible to pass data from server back to client upon a successfull upload. The easiest way is to expand the fileInfo object on the server and add any data that we need. For this, you can use a finished callback:

UploadServer.init({
   ...
   finished(fileInfo, formFields) {
      fileInfo.extraData = "12345676";
   }
});

Client

On client we have a possibility to use pre-defined templates for Bootstrap or Semantic UI, or use the dropzone. We can use several upload forms on the page. We can provide extra data to upload control via formData parameter. We can also limit the file type available for the file picker using parameter fileTypes. Following is an example of how you can include the upload form on your page:

<template name="home">
    <h3>Images</h3>
    {{> upload_bootstrap fileTypes='.jpg' multiple=true formData=specificFormData }}
</template>

or

<template name="home">
    <h3>Drag and drop image on the target area</h3>
    {{> dropzone contentType='images' fileTypes='.jpg' multiple=true formData=specificFormData }}
</template>

Now, you need to specify the formData in the helper:

Template.home.helpers({
  specificFormData: function() {
    return {
      id: this._id,
      other: this.other,
      hard: 'Lolcats'
    }
  }
});

If you need to change the formData dynamically, you can specify it as one of the callbacks (see section Callbacks below).

Following options are available for the template:

Field Type Default Description
contentType String null Describes the content that is uploaded via this control. This becomes part of the 'formData'
fileTypes String null Limits selection of files to specified extensions
multiple bool true Allows to select and upload of multiple files at the same time
formData Object null If necessary, we can send extra form data to the server, this is then available in callbacks under 'formData'

Callbacks

We can also hook onto upload callbacks just like following:

// file: client/init.js
Meteor.startup(function() {
  Uploader.finished = function(index, fileInfo, templateContext) {
    Uploads.insert(fileInfo);
  }
})

If you have several different upload controls on a page and you can execute different callbacks by passing them to the template:

<template name="home">
    {{> upload_bootstrap callbacks=myCallbacks }}
</template>

And then pass the finished in the callback from helper

Template.home.helpers({
  myCallbacks: function() {
    return {
    	formData: function() { return { id: "232323", other: Session.get("ReactiveParam") } },
        finished: function(index, fileInfo, context) { ... },
        ...
    }
  }
})

If you wish to use custom URL for your uploads this can be configured as following:

Uploader.uploadUrl = 'http://yoururl';

Localisation

All texts of the upload control can be set via following setting: va

	Uploader.localisation = {
	browse: "Browse",
	cancelled: "Cancelled",
	remove: "Remove",
	upload: "Upload",
	done: "Done",
	cancel: "Cancel"
}

Logging

You can set the log level via Uploader.logLevel = Uploader.logLevels.debug

Validation

It is possible to validate the uploaded file both on client and on server.

On client you pass the validation function via helper, just like for the finished callback:

<template name="home">
    {{> upload_bootstrap callbacks=myCallbacks }}
</template>

And then pass the finished in the callback from helper

Template.home.helpers({
  myCallbacks: function() {
    return {
        ...
        validate: function(file) { ... }
    }
  }
})

On server, you can configure validation of both, request and the uploaded file using the two functions below. IMPORTANT Validate function has to return a description of error in case validation fails (e.g. validationFailed). In case validation passes, function has to return null. Failed validation also returns code 403.

Use validateRequest to cancel any upload that is not valid BEFORE it starts uploading and save on server resources. Use validateFile to validate the integrity of uploaded file AFTER it was uploaded on the server.

//file:/server/init.js
Meteor.startup(function () {
  UploadServer.init({
    ...
    validateRequest: function(req) {
    	if (req.headers["content-length"] > 1000) {
    	    return "File is too long!";
    	}
    	return null;
    },
    validateFile: function(file, req) {
    	// e.g. read file content
    	if (doSomethingWith(file.path)) {
    	    return "Error Message";
    	}
    	return null;
    }
  })
});

In callbacks, req contains the request data and file contains a following structure:

  • size - file size in bytes
  • path - absolute path on server
  • name - file name
  • type - MIME type (e.g. application/vnd.openxmlformats-officedocument.spreadsheetml.sheet)
  • mtime - UTC of upload time

Custom Templates

It is easy to create a custom template. Following is an example of such:

Template:

<template name="customUpload">
    <form method="POST" enctype="multipart/form-data">
        <input type="file" class="jqUploadclass" data-form-data='{{ submitData }}'>
        {{#with infoLabel}}
            {{ infoLabel}} <button class="start">StartUpload</button>
            <div style="width: 200px; height: 30px; border: 1px solid black">
                <div style="background: red; height: 30px; width: {{ progress }}">
                    {{ progress }}
                </div>
            </div>
        {{/with}}

    </form>
</template>

Javascript:

Template.customUpload.created = function() {
  Uploader.init(this);
}

Template.customUpload.rendered = function () {
  Uploader.render.call(this);
};

Template.customUpload.events({
  'click .start': function (e) {
    Uploader.startUpload.call(Template.instance(), e);
  }
});

Template.customUpload.helpers({
  'infoLabel': function() {
    var instance = Template.instance();

    // we may have not yet selected a file
    var info = instance.info.get()
    if (!info) {
      return;
    }

    var progress = instance.globalInfo.get();

    // we display different result when running or not
    return progress.running ?
      info.name + ' - ' + progress.progress + '% - [' + progress.bitrate + ']' :
      info.name + ' - ' + info.size + 'B';
  },
  'progress': function() {
    return Template.instance().globalInfo.get().progress + '%';
  }
})

Material UI

Thanks to @misteio, here is a little tutorial on how to add Material UI support to uploads via custom templates:

I did it with a custom CSS based on Materialize.

Hope this will help:

In your main template where you want the upload form, you have to add this: {{> customUpload fileTypes='.jpg' formData=uploadHeader callbacks=uploadCallbacks}}

Then create a custom template where you want following this :

<template name="customUpload">
    <form method="POST" enctype="multipart/form-data" class="uk-form">
        <a class="uk-form-file md-btn">{{_ "chooseFile" }}
            <input id="file_upload-select" type="file" class="jqUploadclass header_main_search_btn uk-button-link" data-form-data='{{ submitData }}' accept="{{ fileTypes }}">
        </a>

        {{#with infoLabel}}
            {{ infoLabel}} <button class="header_main_search_btn uk-button-link start"><i class="md-icon material-icons">&#xE2C6;</i></button>
            <div id="file_upload-progressbar" class="uk-progress">
                <div class="uk-progress-bar" style="width:{{ progress }}">{{ progress }}</div>
            </div>
        {{/with}}
    </form>
</template>

And finally add the custom Javascript for the custom Template :

Template.customUpload.created = function() {
    Uploader.init(this);
}

Template.customUpload.rendered = function () {
    Uploader.render.call(this);
};

Template.customUpload.events({
    'click .start': function (e) {
        Uploader.startUpload.call(Template.instance(), e);
    }
});

Template.customUpload.helpers({
    'infoLabel': function() {
        var instance = Template.instance();

        // we may have not yet selected a file
        var info = instance.info.get()
        if (!info) {
            return;
        }

        var progress = instance.globalInfo.get();

        // we display different result when running or not
        return progress.running ?
        info.name + ' - ' + progress.progress + '% - [' + progress.bitrate + ']' :
        info.name + ' - ' + info.size + 'B';
    },
    'progress': function() {
        return Template.instance().globalInfo.get().progress + '%';
    },
    'submitData': function() {
        if (this.formData) {
            this.formData['contentType'] = this.contentType;
        } else {
            this.formData = {contentType: this.contentType};
        }
        return typeof this.formData == 'string' ? this.formData : JSON.stringify(this.formData);
    },
})

And that's it. You can better custom it by yourself, just a little base.

Troubleshooting

  • 503 (Service Unavailable) can have following two reasons
    • You have incorrectly set up your directories for upload or directories have no rights for writing. Please check your server console for any messages.
    • If server console is clean, the problem could be on client with JS debugging tools such as Firebug. Please disable any JS debugging tool and restart your browser. Problem should disappear.

Screenshots

Single file image upload with preview:

Screenshot

Multiple file upload with queue:

Screenshot

Dropzone

Screenshot

meteor-uploads's People

Contributors

aalhaimi avatar alino avatar bestvibes avatar brylie avatar dfrankes avatar jameslefrere avatar kevb avatar krishnapg avatar tomitrescak avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

meteor-uploads's Issues

How can you make different user's file uploads go to different sub-directories on server?

First of all, this seems like a great file upload package. Very easy to get going. Many thanks. And your image reminds me of the movie Zardoz with the floating head -- somehow hypnotic. I see reference on the meteor-tomi-upload-jquery package to DEMO which shows all the different options, but I cannot find that demo in the distribution. So I am wondering the best way to automagically store a given user's file uploads to a subdirectory with that user's id or username or something. Is there a mechanism in place for that?

Breaking changes in v 2.0.0 of jQuery and 1.1.0 of server

New version released with many cool fixes and some breaking changes:

23/1/2015:

  • Full support for Semantic UI
  • Breaking change in 'getFileInfo', 'getDirectory' and 'finished' callbacks, which now include full fileInfo instead of just name and folder. See documentation.
  • Update the DEMO application to showcase all current possibilities
  • Possibility to automatically create directories on server
  • Possibility to delete files on server with UploadServer.delete(path)

Refreshing template

Is it possible to refresh the template back to its original state after its finished successfully. I have an event that shows and hides the uploader template. I'd like to refresh the template back to its original state if it is in its 'successful uploaded state', using this event.

formData not passed along

Im not able to get the formData passed along -- the second callback parameter is always "undefined"

{{> dropzone formData='xxx=name123'}} {{> upload_bootstrap formData='xxx=name123'}}

I20150214-16:29:19.001(-8)? GETDIR { name: '7.sql', size: 2617, type: 'text/x-sql' } undefined
I20150214-16:29:19.002(-8)? FILENAME { name: '7.sql', size: 2617, type: 'text/x-sql' } undefined
I20150214-16:29:19.002(-8)? FIN { name: 'zzz', size: 2617, type: 'text/x-sql', path: 'aaa/zzz' } undefined

My call backs (coffee script sniplets)...

    getDirectory: (fileInfo, formData) ->
        console.log "GETDIR", fileInfo, formData
        return "aaa";
     getFileName: (fileInfo, formData) ->
        console.log "FILENAME", fileInfo, formData
        return "zzz";
      finished: (fileInfo, formFields) -> console.log "FIN", fileInfo, formFields

upload location in init.js

Tomi,

Just a quick question: In the documentation / examples, I see that you were using PWD + "/upload" as the upload location.

But in the meteor-uploads/server/init.js latest version, I see you are not using the PWD() method to get the current work directory. Any reason behind this (such as security etc.) or just a typo?

Personally, I liked your PWD() approach to determine the upload directory automatically, than manually having to rectify it. What do you say?

502 Bad Gateway on Nginx deployment

I have a few meteor apps deployed on subdomains of my Nginx server. Nginx routes these subdomains to the port which each app runs on. I am trying to use meteor-uploads in one of my applications, and I am getting a 502 Bad Gateway error when I attempt an upload.

I'm not sure if this is a problem with how I have Nginx set up, or with deployed meteor projects using meteor-uploads.

Here is a screenshot.

Let me know if you'd like more information (either about my Nginx configuration, or anything else).

I am wondering if I might have to set up some special routing for the /upload path.

Looking in the Nginx error logs, I can see upstream prematurely closed connection while reading response header from upstream, which might lead me to believe that the application is having problems, rather than Nginx.

Issue with exampe

I cloned this repo and the first time I upload an image, this happens (but only the first time after Meteor starts):

W20150305-14:05:17.421(-5)? (STDERR) next(); W20150305-14:05:17.421(-5)? (STDERR) ^ W20150305-14:05:17.422(-5)? (STDERR) TypeError: undefined is not a function

Using meteor-server for a rest api implementation.

Hi,

I'm very glad to say that I'm using your meteor-server for yet another project of mine. I'm trying to build a REST api with meteor and it has an image uploading feature.

Currently, I can upload the file to the server without any problems but as a response (using hostname/upload path) I always get the same answer from the server including file name, path, etc. Is there any way I can change this respond?

I've tried returning a dummy string on "finished" function but I can't see it from client. (This client btw, written in another language and not meteor client) Instead, as I said, I'm getting a json of files including name, path, size, url, etc.

Best,

Is anyone get a files.json dowload link from {{url}}?

If I upload an image or an pdf file, everything works fine. But if I upload a different kind of file, like a .docx, and use {{file.url}} to link to the file, even though it says the correct url, when I click to download, it downloads a "files.json" file. If I use {{file.path}} to link to the file, I get an "unexpected error" message at the link. Has this happened to anyone else? I can see in my database that both the absolute url and the path are correct, so I'm wondering if this is an issue related to file type.

update: I changed the extension from json back to docx, and low and behold, it was my file. So now I am totally miffed, I checked the response headers and they looked correct...really don't understand why it changed the name and extension of my file

Error deploying to meteors free servers

Hey, I feel bad opening up an issue because you were just so fast and responsive for a different one, but I was wondering if you happened to know if this package works with meteor's free demo servers? I've tried deploying with meteor deploy myapp.meteor.com, but the site crashes, and when I look at the logs, it says WARNING Error: EACCES, permission denied '/.uploads/' and sites lines 355 and 61 from the upload_server.js package (checkCreateDirectory and Object.UploadServer.init)

Is this just an inherent limitation of those servers? I've already tried making the directory non-hidden and got the same error, but I haven't deployed it to my digital ocean droplet yet.

Thanks again for any insight!

How to Remove/Delete File from Disk Once Removed from Collection?

Hi,
I wanted to ask that how could I remove a file from disk (from the upload folder) once it has been deleted from the collection.
I presume that the code will be server side meteor code, but I don't know where to start. So please if someone could help with this issue.

Before Hook

Hi again,

I'm playing with codes by merging your server with another front end pieces around there and enjoying so far.

I'm at a point I need to hook the image file object to check it's exif info (with imagemagick currently) so I can save the file by rotating it first.

I've tried to achieve this inside of finished function but unfortunately, imagemagick throws an error as "identify: no data returned"

When I hard-coded the image path lastly uploaded, it works fine.

So I have two questions.

Does finished function run exactly after file saved to the disk?
Is there any way I can achieve this before saving the image to the disk?

Best,

How to add image path to Mongo Collection?

In your example, you have the following text:

finished: function(file, folder, formFields) {
  console.log('Write to database: ' + folder + '/' + file);
}

How do I add the image path/name to a Mongo Collection? I am trying the following without success:

finished: function(file, folder, formFields) {
  var imagePath = folder + '/' + file;
  Images.insert({
    path: imagePath
  });
}

I have the following error on my server console:

 Error: Meteor code must always run within a Fiber. Try wrapping callbacks that you pass to non-Meteor libraries with Meteor.bindEnvironment.

Client side finished function incorrect params in docs

Hi @tomitrescak. Noticed the docs don't include the "index" param in the finished function (client side).

// file: client/init.js
Meteor.startup(function() {
  Uploader.finished = function(fileInfo, templateContext) {
    Uploads.insert(fileInfo);
  }
})

should be

// file: client/init.js
Meteor.startup(function() {
  Uploader.finished = function(index, fileInfo, templateContext) {
    Uploads.insert(fileInfo);
  }
})

Move to Production Server

Tomi,

First off, thank you for this, it is a perfect way to upload files with jQuery and is really simple. When I am on a localhost server, the code works perfectly, uploading to a .uploads folder. However, when I move it to a production server with Nginx and bundle the app, it no longer works and I cannot find the .uploads folder. It throws an 502 error on /upload as it is uploading. Do you have an idea on how to correct this? Or better yet, where to put an uploads folder on my server (running Ubuntu).

Any help is greatly appreciated!

"Finished" function is different between server and client

I'm trying to create a logic to change the filename once it uploads the files and i'm having a conflict between names from the server and the client.

If i have as suggested on the documentation, when i change the filename on my UploadServer, when it finishes, the server knows what is the correct name, but the client doesnt, still gets the original name, therefore it's quite hard to get the image that has been uploaded.

Any suggestion?

if (Meteor.isClient) {
    Uploader.finished = function(index, file) {

        if (!Session.get("UploadedFiles")) {
            Session.set("UploadedFiles", []);
        }

        var files = Session.get("UploadedFiles");
        files.push(file);

        Session.set("UploadedFiles", files);

        // for reactivity you can write to the collection
        // e.g. SomeCollection.insert({path: folder + '/' + file});
        console.log('Write to database: ' + file.name);
    }       
}
if (Meteor.isServer) {
    Meteor.startup(function() {

        UploadServer.init({
            tmpDir          : process.env.PWD + '/.uploads/tmp',
            uploadDir       : process.env.PWD + '/.uploads/',
            uploadUrl       : '/uploads/',
            //imageVersions : { thumbnailBig: {width: 400, height: 300}, thumbnailSmall: {width: 200, height: 100} },
            getFileName     : function(file, formData) {
                return new Date().getTime() + Random.id() + file;
            },
            finished: function(file, folder, formFields) {
                console.log('Write to database: ' + folder + '/' + file);
            }
        });

    });
}

and

client/init.js did not work

Hello,

I tried

// file: client/init.js
Meteor.startup(function() {
  Uploader.finished = function(fileInfo, templateContext) {
    Uploads.insert(fileInfo);
  }
})

(from README.md)
but did not work.

I solved by moving the file to root (and checking if isClient, and using templateContext)

// file: init.js
if (Meteor.isClient) {
  Meteor.startup(function() {
    Uploader.finished = function(fileInfo, templateContext) {
      Uploads.insert(templateContext);
    }
  });
}

I tried this because of the File Load Order.

Thanks

How to add relative path to file as attribute of file object?

I notice that file objects have the following attributes:

  • name
  • size
  • type
  • deleteType
  • deleteUrl
  • url

How can I add the relative path as a file attribute during the upload process? E.g. the path relative to the web root or public folder root ("/images/image.png").

File uploaded but 'finished' not triggered

Weird problem, which is only present in remote server (works well in localhost), not sure what I'm doing wrong

  • The file is uploaded to the folder
  • Progress goes to 100%
  • Progress bar reverts back to 0
  • Button flashes 'done' then goes back to 'cancel'
    I'm then unable to upload a new file, any work arounds?

Error after insert response data to databse

In Uploader.finished function, I insert information of the uploaded file into database. Then, I got the following error:

Exception in template helper:
TypeError: Cannot read property 'get' of undefined
at Object.Template.upload_bootstrap.helpers.showQueue .... tomi_upload-jquery.js?2e9ed128a1fb4fd51a0b00d241223f0e28b82306:2741:26)

Uploads do not work with Cordova

Does not work following the readme. Special settings for Cordova builds?

Failed 200 OK
data.sumbit.always: textStatus= parsererror

iOS simulator

UploadServer.init({
    tmpDir: process.env.PWD + '/public/uploads/tmp',
    uploadDir: process.env.PWD + '/public/uploads/',
    checkCreateDirectories: true
});

How to override image path to remove /images/ from path?

When uploading images to the server, I notice that the images are placed in an images subfolder of the upload_dir location. How can I upload directly to the specified upload_dir rather than auto-creating an images subfolder?

I have the following configuration:

var base_dir = process.env.PWD;
var upload_dir = base_dir + '/public/';
var temp_directory = base_dir + '/public/images/tmp';

Meteor.startup(function () {
    UploadServer.init({
        tmpDir: temp_directory,
        uploadDir: upload_dir,
        getDirectory: function (file, formData) {
            return formData.contentType;
        }
    });
});

503 Error

I've decided to use your upload methods instead of collectionfs thingy however,

I am getting a
POST http://localhost:3000/upload 503 (Service Unavailable)
error on upload.

I followed the instructions as in readme. What could be the problem?

Thanks for the work!

Error: You're not in a Meteor project directory.

Cloned the repository to local disk and while trying to run the app with 'meteor' command getting the error "You're not in a Meteor project directory."

Not sure what the problem is. 'meteor add' and 'meteor list' also are not working. (same error).

{{> upload_bootstrap }} failed in Uploader.init

template fails with the following error:

Uncaught TypeError: Cannot set property 'queueView' of nulluploader.js:91 Uploader.initupload_bootstrap.js:3 Template.upload_bootstrap.createdtemplate.js:126 (anonymous function)view.js:206 fireCallbackstracker.js:480 Tracker.nonreactiveview.js:203 (anonymous function)view.js:414 Blaze._withCurrentView

the failed line is: this.data.queueView = new ReactiveVar([]);
where this.data is null.

UploadServer.init was called (I checked that with console.log)

Filename and Folder

How do I get the filename and folder in the client? because I need to use it in a form

autoStart

How do i automatically start the upload as soon as i drag and drop the file?

I found one reference to it on the code "autoStart" but not sure how to make this work.

I tried something like:
{{> upload_semanticUI autoStart=true }}

Can't find in the documentation, could you please light some shed to me on this please?

thanks

Clientside 'multiple' parameter not taken into account

Hi,

When I set the 'multiple' parameter to false within the bootstrap template, the HTML output always renders multiple=true. Looking at the template source:

<div class="btn btn-primary btn-file upload-control">
    Browse&hellip;
    <input type="file" class="jqUploadclass" multiple="true" data-content-category="{{ contentType }}" data-form-data='{{ submitData }}' accept="{{ fileTypes }}">
</div>

Seems an easy fix to incorporate multiple="{{multiple}}"

For now, you can also fix this clientside using jQuery:

Template.NAME.rendered = function() {
  //set multiple uploads to false, yet bug in template...
  $(".jqUploadclass").prop('multiple',false);
};

upload_semantic_ui does not call init() and other problems.

I'm trying out your controls and I gotta say, if I could iron out some the issues.. It would exactly what I am looking for in my app!

Looking at your projects history, I think that since upload_bootstrap has been revamped, semantic_ui has taken a few blows,

The first problem I've ran into is that the .created() is not being applied, so globalInfo is undefined, since init() isn't being called.

Suggestion: add --- 8< ---

Template['upload_semantic_ui'].created = function () {
Uploader.init.call(this);
};

--- 8< --- to meteor-tomi-upload-jquery/upload_semantic_ui.js

And that seemed to fix the undeclared variables issue, however, even after that there are some troubles getting the upload to actually happen. I'm looking into it further, but I thought I would share what I got so far.

How do I pull the formData from the finished callback?

Hello,

Could you please help me out. I'm trying to basically upload a blog image and associate it with one individual blog post. I'm assigning the blog _id to formData on the template. Is there a way that I can get this data in the finished callback? That way I could update the blog record with the correct image url. Below is the source:

{{> upload_bootstrap formData=_id}}
  UploadServer.init({
    tmpDir: process.env.PWD + '/.uploads/tmp',
    uploadDir: process.env.PWD + '/.uploads/uploads',
    finished: function(fileInfo, formData) {
        console.log(formData);
        Campaigns.update({_id: formData}, {set: {image: fileInfo.path}});
    }
  })

Any suggestions would be great. Thanks for all your help.

Amazing package!

Keep up the good work, It's really awesome. Finally some really useful and well built uploading package. Thank you.

Support for Windows

Hi

Trying to run this on Windows. process.env.PWD isnt' available so I tried the full path and process.cwd() to no avail. I just get a double C:\ in the path.

Error: ENOENT, no such file or directory 'C:\C:\dev\infoAdmin\.meteor\local\build\programs\server'

Any clue what I might need to do?

503 (Service Unavailable)

Hello,

While I am uploading, I get error:

screen shot 2015-01-20 at 12 26 47 pm

My html code:

<div class='import'>
  {{> upload_bootstrap multiply=yes }}
</div>

unexpected server error

Hi,

I followed your steps in the document to try the simplest example. But I run into trouble. Something wrong on the server side. The console output as below,

W20150213-16:23:17.156(8)? (STDERR)
W20150213-16:23:17.160(8)? (STDERR) /home/roger/.meteor/packages/tomi_upload-server/.1.1.1.b4xvxt++os+web.browser+web.cordova/npm/node_modules/connect/lib/middleware/static.js:60
W20150213-16:23:17.160(8)? (STDERR) next();
W20150213-16:23:17.160(8)? (STDERR) ^
W20150213-16:23:17.162(8)? (STDERR) TypeError: undefined is not a function
W20150213-16:23:17.162(8)? (STDERR) at resume (/home/roger/.meteor/packages/tomi_upload-server/.1.1.1.b4xvxt++os+web.browser+web.cordova/npm/node_modules/connect/lib/middleware/static.js:60:7)
W20150213-16:23:17.162(8)? (STDERR) at SendStream.error (/home/roger/.meteor/packages/tomi_upload-server/.1.1.1.b4xvxt++os+web.browser+web.cordova/npm/node_modules/connect/lib/middleware/static.js:73:37)
W20150213-16:23:17.162(8)? (STDERR) at SendStream.emit (events.js:95:17)
W20150213-16:23:17.163(8)? (STDERR) at SendStream.error (/home/roger/.meteor/packages/tomi_upload-server/.1.1.1.b4xvxt++os+web.browser+web.cordova/npm/node_modules/connect/node_modules/send/lib/send.js:147:51)
W20150213-16:23:17.163(8)? (STDERR) at SendStream.onStatError (/home/roger/.meteor/packages/tomi_upload-server/.1.1.1.b4xvxt++os+web.browser+web.cordova/npm/node_modules/connect/node_modules/send/lib/send.js:248:48)
W20150213-16:23:17.163(8)? (STDERR) at /home/roger/.meteor/packages/tomi_upload-server/.1.1.1.b4xvxt++os+web.browser+web.cordova/npm/node_modules/connect/node_modules/send/lib/send.js:320:26
W20150213-16:23:17.163(8)? (STDERR) at Object.oncomplete (fs.js:107:15)

Can not find the next() definition.

Could you help me?

Finished and Fiber

first off thanks for your work. I try to insert a record in a collection after upload is finished but I get the error "error: meteor code must always run within a fiber". I try to use meteor wrapAsynch function but the Fiber is not active (Fiber.current is undefined). I resolve it to wrap my code in a Fiber(...).run scope, is it the correct way?

Thanks.

Clear uploader

No way to clear the uploader at will after an upload without refreshing the page.

Error in Uploader.finished

Hi,
I have the following problem:
1)Template:
{{> upload_bootstrap contentType='images' multiple=true formData=uploadFormData}}
2) Helper:
uploadFormData: function() {
return {
module: 'news',
prefix: this.news.slug
};
}
3) In Uploader.finished function:
Meteor.call('editNews', that.data._id, {
$addToSet: {
images: file
}
});
=> I got errors:
Exception in template helper: TypeError: Cannot read property 'get' of undefined
at Object.Template.upload_bootstrap.helpers.progress (http://localhost:3000/packages/tomi_upload-jquery.js?9aa27a89f7d195f096c5bbb084492066153413df:2719:38)
at bindDataContext (http://localhost:3000/packages/blaze.js?efa68f65e67544b5a05509804bf97e2c91ce75eb:2727:16)
at Blaze._wrapCatchingExceptions (http://localhost:3000/packages/blaze.js?efa68f65e67544b5a05509804bf97e2c91ce75eb:1606:16)
at Spacebars.call (http://localhost:3000/packages/spacebars.js?3c496d2950151d744a8574297b46d2763a123bdf:169:18)
at Spacebars.mustacheImpl (http://localhost:3000/packages/spacebars.js?3c496d2950151d744a8574297b46d2763a123bdf:106:25)
at Object.Spacebars.mustache (http://localhost:3000/packages/spacebars.js?3c496d2950151d744a8574297b46d2763a123bdf:110:39)
at Template.upload_bootstrap.HTML.FORM.HTML.DIV.HTML.DIV.HTML.DIV.style (http://localhost:3000/packages/tomi_upload-jquery.js?9aa27a89f7d195f096c5bbb084492066153413df:2639:24)
at Object.Blaze._withCurrentView (http://localhost:3000/packages/blaze.js?efa68f65e67544b5a05509804bf97e2c91ce75eb:2043:12)
at Blaze._HTMLJSExpander.def.visitAttribute (http://localhost:3000/packages/blaze.js?efa68f65e67544b5a05509804bf97e2c91ce75eb:1971:21)
at HTML.TransformingVisitor.def.visitAttributes (http://localhost:3000/packages/htmljs.js?567eb96d5d22631c03d6aca6afa4c42f0d1295f2:228:44)
....
Perhaps after update news cause template re-render with wrong context.
Thanks!

lacking Security controls: provide application control over the security and permission to upload

Currently, the is no user information provided, and there is no server-side control over who is uploading files.

  1. Meteor.user(), information needed within callbacks

Mteor.user() must be called from within a fiber, so it cannot be called directly from the callbacks. Suggest that the user information is passed along so it is possible to check if the user are allowed to upload files, or better that the call is wrapped in a fiber so any meteor library can be used from within the callback. (for example, use helper functions rather than callbacks)

  1. Provide a callback to reject the file upload.

There is no server side way of signaling that the file cannot be accepted -- e.g. as a result of user not having permissions. Make the callback(or helper functions) able to return a "reject" with an error message.

imageVersions returning errors

I'm trying to generate different versions of my image using the imageVersions property but i'm getting an error.

imageVersions   : { thumbnailBig: {width: 400, height: 300}, thumbnailSmall: {width: 200, height: 100} },
W20150122-00:31:00.040(11)? (STDERR)
W20150122-00:31:00.041(11)? (STDERR) events.js:72
W20150122-00:31:00.041(11)? (STDERR)         throw er; // Unhandled 'error' event
W20150122-00:31:00.041(11)? (STDERR)               ^
W20150122-00:31:00.041(11)? (STDERR) Error: spawn ENOENT
W20150122-00:31:00.041(11)? (STDERR)     at errnoException (child_process.js:1001:11)
W20150122-00:31:00.041(11)? (STDERR)     at Process.ChildProcess._handle.onexit (child_process.js:792:34)

Removing the option works fine.

FYI: I have installed imagemagick sudo npm install imagemagick -g

Any idea?

semanticUI Bug?

I think i found a bug whilst trying to change the classes of the semanticUI

I have setup mine like below (not sure if i'm doing correct because i couldn't find anything on the documentation,please let me know)

    Uploader.UI.semanticUI = {
        upload: 'media-browse',
        progressOuter: 'media-browse-progress-outer',
        progressInner: 'media-browse-progress-inner',
        progressBar: 'media-browse-progress-bar',
        removeButton: 'media-browse-remove',
        removeButtonIcon: '',
        startButton: 'media-browse-btn-start',
        startButtonIcon: '',
        doneButton: 'media-browse-btn-done',
        doneButtonIcon: '',
        cancelButton: 'media-browse-btn-cancel',
        cancelButtonIcon: '',
        cancelledButton: 'media-browse-btn-canceled'
    }

Also, if i may suggest, this could be merged into the defaults. So if i want to change just a name of one of the elements, i wouldn't have to replicate the whole object in order to do that.

So, back to the bug, If i replace the element startButton to whatever class i want, it doesnt work. The event might be still appended to the 'start' class because if i do the below it works.

startButton: 'start media-browse-btn-start',

I haven't digged into the code to be 100% sure but i think it's worth a look! :)

Hope it's fine to keep logging bugs that i find! :)

Thanks

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.