{"id":15705210,"url":"https://github.com/phstc/uploader_rails","last_synced_at":"2025-04-16T07:35:22.283Z","repository":{"id":3605593,"uuid":"4670302","full_name":"phstc/uploader_rails","owner":"phstc","description":"It's a file upload with progress implemented in Rails, integrated with Node.js","archived":false,"fork":false,"pushed_at":"2012-09-14T00:54:44.000Z","size":251,"stargazers_count":5,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-29T05:11:26.681Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"http://superuploads.herokuapp.com/","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/phstc.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2012-06-15T01:14:52.000Z","updated_at":"2014-01-07T20:05:03.000Z","dependencies_parsed_at":"2022-09-11T00:22:42.336Z","dependency_job_id":null,"html_url":"https://github.com/phstc/uploader_rails","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phstc%2Fuploader_rails","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phstc%2Fuploader_rails/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phstc%2Fuploader_rails/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phstc%2Fuploader_rails/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/phstc","download_url":"https://codeload.github.com/phstc/uploader_rails/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249213752,"owners_count":21231096,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-03T20:14:59.807Z","updated_at":"2025-04-16T07:35:22.213Z","avatar_url":"https://github.com/phstc.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"It's my solution to the Code Challenge [File Upload with Progress](https://github.com/phstc/uploader_rails/blob/master/BackendDeveloperChallengeUpdated.pdf).\n\nI decided to split the challenge into two small projects, an [Uploader in Node.js](https://github.com/phstc/uploader_nodejs) and an [Uplader client in Rails](https://github.com/phstc/uploader_rails). It's a kind of System of Systems concept. Node.js fits better for the upload (event-driven, non-blocking I/O) and Rails fits better for the client (gems, community, maturity etc).\n\n[![Build Status](https://secure.travis-ci.org/phstc/uploader_rails.png)](http://travis-ci.org/phstc/uploader_rails)\n\n\n##How it Works\n\n* When an user go to the [superuploads](http://superuploads.herokuapp.com)\n* Click in the menu Uploads -\u003e New Upload\n    1. A socket.io connection is opened \n* When an user select a file\n    1. The client submits a form to a hidden iFrame targeting the node.js uploader\n    2. While uploader is receiveing the upload buffer, it emits the received percentage to the client\n    3. The client receives the upload percentage and update the view\n    4. When the upload is finished the client sets an hidden input with the file url\n* The user fill the description \u0026 save\n* ...\n\n##Uploder Node.js\n\n###Why Node.js?\n\nI could do the Uploader using XmlHttpRequest or Flash, there are lot of cross-browser plugins for that, I also tested [file-uploader](https://github.com/valums/file-uploader), there is a [branch](https://github.com/phstc/uploader_rails/tree/valums-file-uploader) with this version, but only plugins entirely in Flash worked in all browsers then I decided to keep it in Node.js instead of browser based solutions. BTW... I don't like the idea to use Flash.\n\n###Server\n\nTo configure Node.js on Amazon EC2, I followed my post [Configurando o Node.js no Amazon EC2](http://pablocantero.com/blog/2012/01/04/configurando-o-node-js-no-amazon-ec2/) (disabling Nginx). \nI like this post \"recipe\", it makes the server similar as a PaaS, but to do it more AutoScaling focused, it needs a different approach e.g. add the Server SSH Keys in the GitHub, create an image, an initialization script to clone the repository, CloudWatch and ELB.\n\n###Node modules\n\n####[node-static](https://github.com/cloudhead/node-static)\n\nI would like to use Nginx to serve the static content, but even with ```proxy_buffering off```, Nginx still buffering the upload before send it to the Node.js. That's the why I used the node-static to serve the uploaded files. \n\nI found a 'bug' in the node-static, I fixed it and sent a [pull request #54](https://github.com/cloudhead/node-static/pull/54) to the project.\n\nRecently [cloudhead](https://github.com/cloudhead) added me as a contributor in the project. I reviewed and merged few pull requests and started adding tests in the project. Firstly, integration tests, they were easier than unit tests in this case. I used [vows](https://github.com/cloudhead/vows), I also sent a [pull request #222](https://github.com/cloudhead/vows/pull/222) to vows.\n\nIn a high traffic scenario, I would like to remove the static content server from Node.js, maybe using [HAProxy](http://haproxy.1wt.eu/) proxying to Nginx or Apache and the Uploader.\n\n####[socket.io](http://socket.io)\n\nI used socket.io to emit the upload progress to the client, it has lot of fallbacks, making it fully compatible most used browsers.\n\nMotivated by this project I created the [node-upload-progress](http://github.com/phstc/node-upload-progress) module to handle upload and progress. This module does not depends on socket.io, it uses a similar mechanism to [Nginx Upload Progress Module](http://wiki.nginx.org/HttpUploadProgressModule).\n\nIn a high traffic scenario, I would like to use the node-upload-progress approach instead of socket.io.\n\n####[formidable](https://github.com/felixge/node-formidable)\n\nJust to parse the form data.\n\n####[mocha](https://github.com/visionmedia/mocha)\n\nFor tests.\n\n##Uploader client Rails\n\n###Why Rails?\n\nNowadays Ruby became my main programming language, most part of my Ruby projects I used Rails, I'm really productive with them, that's the why I chose Ruby on Rails.\n\n\u003e became my main programming language\n\nIt means that I like the Ruby object model, the community... The Ruby ecosystem.\n\n###Rails enviroment\n\nI used this template http://drone.bz/49748da6-3c22-4b85-b4fe-3346a5865ce5 to create my Rails project.\n\n```rails new superuploads --builder=http://drone.bz/49748da6-3c22-4b85-b4fe-3346a5865ce5.rb```\n\nI also added Capyara, it isn't include in the template.\n\nThe Rails version is hosted on Heroku.\n\n##Security hash\n\nAs I decided to develop this Challenge splitting in Rails for the Client and Node.js for the Uploader. I felt that I didn't write much code, Rails makes CRUD operations easy, Node.js makes the upload easy, mixing both resulted in much less code.\n\nTo write a little bit more code, I wrote a security_hash mechanism to ensure that the upload request is valid. Client and Uploader know the SECRET_KEY, all upload requests must contain security_hash ```md5(SECRET_KEY + timestamp)``` and timestamp.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fphstc%2Fuploader_rails","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fphstc%2Fuploader_rails","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fphstc%2Fuploader_rails/lists"}