Skip to content

Home

How to Upload Files with Meteor.js?

Welcome to another episode of Continuous Improvement where we discuss ways to enhance your development skills and solve common coding challenges. I'm your host, Victor. Today, we're going to talk about handling file uploads in a Meteor project.

Last week, a friend of mine ran into an issue when deploying his Meteor app with a file upload feature. It worked perfectly fine on his local machine, but once deployed, the server kept refreshing and failed to load any page. After investigating this issue, I found a solution that I want to share with you all.

The problem arises when using cfs:filesystem, which uploads the file to a public folder directory. This is not allowed by the server for security reasons, resulting in the page failing to load. However, we have a workaround to solve this issue by using GridFS as a storage adapter to insert files into MongoDB.

Let's go through the steps to implement this solution in your Meteor project.

First, you need to install the necessary packages. Replace cfs:filesystem with cfs:gridfs in your project.

Open your terminal and enter the following commands:

meteor add cfs:standard-packages
meteor add cfs:gridfs

Great! Once you've added the required packages, you can move on to the syntax changes. Instead of using FS.Collection, switch to FS.Store.GridFS when declaring your collection.

var imageStore = new FS.Store.GridFS("images");

Images = new FS.Collection("images", {
 stores: [imageStore]
});

Now, let's configure the permissions for your collection. Add the following deny and allow rules based on your requirements.

Images.deny({
 insert: function(){
 return false;
 },
 return false;
 },
 remove: function(){
 return false;
 },
 download: function(){
 return false;
 }
});

Images.allow({
 insert: function(){
 return true;
 },
 return true;
 },
 remove: function(){
 return true;
 },
 download: function(){
 return true;
 }
});

Moving on to the user interface. In your client template, add a file input button for users to select their file.

<input type="file" name="..." class="myFileInput">

Now, let's handle the file upload event in your template.

Template.Profile.events({
   'change .myFileInput': function(event, template) {
      FS.Utility.eachFile(event, function(file) {
        Images.insert(file, function (err, fileObj) {
          if (err){
             // handle error
          } else {
             // handle success depending on your needs
            var userId = Meteor.userId();
            var imagesURL = {
              "profile.image": "/cfs/files/images/" + fileObj._id
            };
            Meteor.users.update(userId, {$set: imagesURL});
          }
        });
      });
   },
});

Don't forget to set up the publication and subscription if you have removed the autopublish package.

Meteor.publish("images", function(){ return Images.find(); });

Subscribe to it in your iron:router to ensure that you have the necessary data when rendering the template.

Router.route('/profile',{
 waitOn: function () {
 return Meteor.subscribe('images')
 },
 action: function () {
 if (this.ready())
 this.render('Profile');
 else
 this.render('Loading');
 }
});

That's it! By following these steps, you can successfully handle file uploads in your Meteor project, even when deployed to a server. If you're using an Amazon S3 bucket, consider using cfs:s3 as the adapter. And as a last resort, consider Filepicker as an alternative approach for file uploads.

I hope this solution helps you overcome any file upload challenges you may encounter in your projects. Remember, continuous improvement is key to becoming a better developer.

Thank you for listening to this episode of Continuous Improvement. Stay tuned for more tips, tricks, and solutions to enhance your coding journey. I'm Victor, your host, signing off.

如何使用Meteor.js上傳檔案?

注意: 本教程使用的是2014年12月15日的Meteor 1.1.3 和 cfs:standard-package 0.0.2。由於此功能正在積極開發中,您閱讀此文時可能已有所變化。如果你有任何疑問,請隨時聯絡我。:)

問題描述

上周,我的一個朋友問我如何在Meteor項目中處理檔案上傳。我建議他使用Collection FS,並按照他們存儲庫的README.md指南。檔案上傳功能在本地主機上工作正常,但一旦部署到免費的Meteor測試服務器,就會失敗。事實上,服務器會不斷刷新,甚至無法加載頁面。

我的解釋

這個問題產生的原因是 FS.filesystem 將圖像上傳到公共資料夾目錄。由於安全考慮,除非經過適當配置,否則服務器不允許這樣做。一個解決方法是使用 GridFS 作為儲存適配器,將圖像插入到MongoDB中。

我的解決方案

安裝

首先,不要使用cfs:filesystem,而要為您的套件使用cfs:gridfs

    meteor add cfs:standard-packages
    meteor add cfs:gridfs
語法

接下來,當聲明您的集合時,從使用 FS.Collection 切換到 FS.Store.GridFS

var imageStore = new FS.Store.GridFS("images")

Images = new FS.Collection("images", {
  stores: [imageStore],
})
權限

然後,根據你的需求設定'deny'和'allow'規則。

Images.deny({
  insert: function () {
    return false
  },
  update:
  created: function () {
    return false
  },
  remove: function () {
    return false
  },
  download: function () {
    return false
  },
})

Images.allow({
  insert: function () {
    return true
  },
  update:
  created: function () {
    return true
  },
  remove: function () {
    return true
  },
  download: function () {
    return true
  },
})
使用者介面

在客戶端模板中添加一個檔案輸入按鈕以供使用者點擊。

<input type="file" name="..." class="myFileInput" />

像這樣處理事件:

Template.Profile.events({
  "change .myFileInput": function (event, template) {
    FS.Utility.eachFile(event, function (file) {
      Images.insert(file, function (err, fileObj) {
        if (err) {
          // handle error
        } else {
          // handle success depending on your needs
          var userId = Meteor.userId()
          var imagesURL = {
            "profile.image": "/cfs/files/images/" + fileObj._id,
          }
          Meteor.users.update(userId, { $set: imagesURL })
        }
      })
    })
  },
})
發佈/訂閱

最後,如果你已經移除了 autopublish 套件,不要忘記設定發佈和訂閱。

Meteor.publish("images", function () {
  return Images.find()
})

在你的 iron:router 中訂閱它:

Router.route("/profile", {
  waitOn: function () {
    return Meteor.subscribe("images")
  },
  action: function () {
    if (this.ready()) this.render("Profile")
    else this.render("Loading")
  },
})

我希望這個解決方案對你有所幫助。如果你正在使用Amazon S3 bucket,可以考慮使用 cfs:s3 作為適配器。如果所有其他方法都失敗了,Filepicker可以作為處理文件上傳的另一種方法。欲了解更多信息,請訪問 Filepicker的網站

Q&A with General Assembly Hong Kong

I was invited by General Assembly (GA) Hong Kong to talk about my experience in the Web Development Immersive (WDI) course.

1. Introduce Yourself and Describe Your Current Projects

My name is Victor, and I am a software engineer. Currently, I am working on several interesting projects that utilize JavaScript frameworks:

  1. A native iOS/Android mobile app using Ionic and the Neo4j graph database.
  2. A video chatroom using WebRTC, Node.js, and Express.js.
  3. A music visualizer using WebGL and Three.js.
  4. A LinkedIn-like network platform using Angular.js and MongoDB.
  5. A real-time voting system using Meteor.js and D3 data visualization.

Some of these are open-source projects. If you're interested in contributing or trying out the demos, please check out my GitHub.

2. Reasons for Choosing WDI at GA

Prior to enrolling in WDI at GA, I was a digital marketer responsible for social media promotions in Australia. My role sparked an interest in how technology is rapidly changing traditional media and marketing channels. Recognizing the importance of a good website as the cornerstone of digital marketing efforts, I was motivated to develop coding skills. I chose WDI at GA over night classes at a Hong Kong university because I wanted an education that was in tune with cutting-edge technologies.

3. Recapping the Student Experience

My favorite part of the WDI course was the camaraderie among students from diverse backgrounds. We all helped each other technically and emotionally. Web development is teamwork, and a website is too complex to build entirely on your own, regardless of your skill level.

4. How the Course Helped Achieve My Goals

My goal was to land a job in the industry, and GA's strong network in Hong Kong greatly assisted me. I networked extensively and participated in various events, including hackathons. Special thanks to Justin for his support during this period.

5. Top 3 Lessons from the Course

  1. Wireframing: Initially, I underestimated the importance of wireframing. With more project experience, I’ve come to realize that planning ahead saves time in the long run.
  2. User Testing: Continuous user feedback is crucial. Code should be driven by market demand and user needs, not just by what a developer thinks is cool.
  3. Learning How to Learn: The course couldn’t cover everything, so self-directed learning is crucial for ongoing development.

6. Life After GA: What's Next?

I abide by the principle of "Always Be Coding." The more you code, the better you get. Currently, I am strengthening my theoretical foundation to take on leadership roles in the IT industry.

Q&A with General Assembly Hong Kong

Welcome to Continuous Improvement - the podcast where we delve into the world of web development, share stories, and explore ways to continuously improve our skills and projects. I'm your host, Victor, a software engineer with a passion for coding and a thirst for knowledge.

In today's episode, we'll be discussing my experience in the Web Development Immersive course at General Assembly Hong Kong. But before we dive in, let me give you a brief overview of what I'm currently working on.

At the moment, I'm involved in several exciting projects that make use of JavaScript frameworks. One project is a native iOS/Android mobile app using Ionic and the Neo4j graph database. Another is a video chatroom built with WebRTC, Node.js, and Express.js. And then there's a music visualizer using WebGL and Three.js. Additionally, I'm working on a LinkedIn-like network platform using Angular.js and MongoDB, as well as a real-time voting system using Meteor.js and D3 data visualization. Some of these projects are open-source, so if you're interested in contributing or checking out demos, head over to my GitHub page at github.com/victorleungtw.

Now, let's rewind a bit and talk about my decision to enroll in the Web Development Immersive course at General Assembly. Before diving into web development, I was actually a digital marketer handling social media promotions in Australia. This job sparked my curiosity about how technology is transforming traditional media and marketing channels. Realizing the significance of having a strong web presence, I wanted to develop my coding skills. I chose the WDI course at General Assembly because I wanted an education that matched the pace of cutting-edge technologies.

Moving on, I want to share some insights about the student experience at General Assembly. One of my favorite aspects of the WDI course was the sense of camaraderie among students. We all came from different backgrounds, but we helped and supported each other both technically and emotionally. Building a website is a team effort, no matter your skill level.

Now, let's talk about how the course helped me achieve my goals. My primary objective was to secure a job in the web development industry, and General Assembly's strong network in Hong Kong greatly facilitated that process. I actively networked and participated in various events, such as hackathons. I'm grateful for the support of Justin, who played a significant role during this period.

Throughout the course, I learned countless lessons, but let me share the top three takeaways with you.

Lesson number one is the importance of wireframing. Initially, I underestimated the significance of planning ahead. But as I gained more project experience, I realized that taking the time to wireframe can save us a lot of time in the long run.

Lesson number two is all about user testing. It's crucial to continuously gather feedback from users. After all, code should be driven by market demand and user needs, not solely by what a developer thinks is cool.

Lastly, lesson number three is learning how to learn. The WDI course provided a strong foundation, but technology is ever-evolving. This means that ongoing self-directed learning is crucial to stay on top of the game.

Now that I've completed the course, you might be wondering what's next for me. Well, I live by the principle of "Always Be Coding." The more we code, the better we become. Currently, I'm focusing on strengthening my theoretical foundation to prepare for leadership positions within the IT industry.

And that's a wrap for today's episode of Continuous Improvement. Thank you for joining me on this journey as we explore the world of web development and share our experiences. If you have any questions, suggestions, or topics you'd like us to cover in future episodes, feel free to reach out to me on social media. You can find me on Twitter and LinkedIn. Stay tuned for more episodes focused on continuous improvement in the world of web development. Until next time, keep coding and keep improving!

與香港General Assembly的問答環節

我被香港General Assembly (GA) 邀請,談論我在Web Development Immersive (WDI) 課程裡的經驗。

1. 自我介紹並描述你目前的項目

我叫Victor,是一名軟件工程師。目前,我正在進行幾個利用JavaScript框架的有趣項目:

  1. 使用Ionic和Neo4j圖形數據庫的原生iOS/Android手機應用程式。
  2. 使用WebRTC,Node.js,和Express.js的視頻聊天室。
  3. 使用WebGL和Three.js的音樂視覺化器。
  4. 使用Angular.js和MongoDB的LinkedIn風格的網絡平台。
  5. 使用Meteor.js和D3數據視覺化的實時投票系統。

其中一些是開源項目。如果你有興趣參與或試用demo,請查看我的GitHub

2. 選擇在GA接受WDI的原因

在參加GA的WDI課程之前,我在澳洲負責社交媒體推廣的數字營銷人員。我的角色激發了我對科技如何迅速改變傳統媒體和市場渠道的興趣。認識到良好網站為數字營銷努力的基石的重要性,我有了開發編碼技能的動力。我選擇在GA接受的WDI而非在香港一所大學夜間上課,是因為我想要一種與最前沿技術保持同步的教育。

3. 回顧學生經驗

我在WDI課程中最喜歡的部分是來自多樣化背景的學生之間的友誼。我們都在技術上和情感上互相幫助。網頁開發是團隊合作,一個網站太複雜,無法完全靠自己建立,無論你的技術水平如何。

4. 課程如何幫助我實現我的目標

我的目標是在這個行業找到工作,GA在香港的強大網絡對此大有幫助。我大量的社交並參與了各種活動,包括黑客馬拉松。對於Justin在這期間的支持表示特別感謝。

5. 課程的前3個經驗

  1. Wireframing:起初,我低估了wireframing的重要性。隨著更多的項目經驗,我已經意識到預先計劃可以長遠節省時間。
  2. 用戶測試:持續的用戶反饋非常重要。代碼應該由市場需求和用戶需求驅動,而不僅僅是由開發人員認為這很酷。
  3. 學習如何學習:課程無法涵蓋所有內容,所以對於持續的發展,自我導向的學習是非常重要的。

6. 過了GA後的生活:接下來是什麼?

我堅守"總是在編碼"的原則。你編碼的越多,你獲得的技能就越好。目前,我正在加強我的理論基礎,以便在IT產業中承擔領導角色。

Does Hack Reactor Make You Smarter?

The Daily Routine

Every morning, I wake up at 12 a.m. My alarm clock helps me start my day with the goal of becoming a software engineer. As a remote student in Hong Kong, I'm 16 hours ahead of San Francisco time. Adapting to this time difference hasn't been easy. The course material only adds to the complexity, covering topics like recursion, hash tables, pseudo-classical inheritance, Backbone, and Express, among others. So, what am I gaining from this experience?

Learning to Think Critically

Professional software engineers create exceptional products not just because they are skilled coders, but also because they have the right mindset. How proficient they are with a particular framework is just one factor. They are also fast and consistent learners, effective and empathetic communicators, and motivated, inquisitive problem solvers. These skills can't be learned from books or online videos alone; they come from hands-on practice, observing how instructors approach problems, and learning from mentors.

Learning from More Knowledgeable Peers

The coding bootcamp attracts many intelligent individuals, setting it apart from other learning platforms. I often ask myself, "Am I smart enough for this prestigious institution?" The feeling of imposter syndrome is real. Interacting with smarter people can sometimes be intimidating and make me feel inadequate. However, it also pushes me to be more comfortable with making mistakes, failing, and thereby learning at a faster rate.

Does Coding Make Me Smarter?

I believe it does, and what we believe often becomes a self-fulfilling prophecy. Working with intelligent people enhances the way I approach and think about challenges. There is always a better, more effective, and simpler way to do things. The smarter the people you surround yourself with, the more you are likely to learn from them, consequently becoming more intelligent yourself.

Does Hack Reactor Make You Smarter?

Welcome to Continuous Improvement, the podcast where we explore personal growth and development through the lens of daily routines. I'm your host, Victor, and today we're diving into the world of software engineering and the impact it can have on our intelligence.

Have you ever wondered how software engineers create exceptional products? It's not just about writing code. It's about having the right mindset and continuously improving our skills. But where do we learn these skills? Is it just from books and online videos?

In a recent blog post titled "The Daily Routine", the author shares their experience as a remote student studying to become a software engineer. They start their day at 12 a.m., being 16 hours ahead of San Francisco time in Hong Kong. Talk about dedication! The course material covers complex topics like recursion, hash tables, and various frameworks. But what stands out is their focus on the daily routines that help them become a better software engineer.

One key aspect highlighted in the blog post is the importance of thinking critically. Being a skilled coder is just one part of the equation. Professional software engineers are fast and consistent learners, effective communicators, and motivated problem solvers. These skills are developed through hands-on practice, observing instructors, and learning from mentors. It's not just about learning from textbooks; it's about experiencing the real challenges of coding.

Another interesting point raised is the value of learning from smarter peers. The author admits feeling inadequate and experiencing imposter syndrome when surrounded by intelligent individuals. But instead of discouragement, the author uses this as an opportunity to learn at a faster rate. It's about embracing the discomfort of being around more knowledgeable peers and growing from that experience.

So, does coding actually make us smarter? The author believes it does and I couldn't agree more. The mindset we adopt and the people we surround ourselves with have a direct impact on our growth. As the saying goes, "You are the average of the five people you spend the most time with." When we interact with intelligent individuals, we push ourselves to think differently, to explore better solutions, and ultimately increase our own intelligence.

And that's a wrap for today's episode of Continuous Improvement. We've explored the daily routines of a software engineering student and how coding can enhance our intelligence. Remember, it's not just about the technical skills, but also about our mindset and surroundings.

If you enjoyed this episode, be sure to subscribe to Continuous Improvement on your favorite podcast platform. And don't forget to leave a review and share it with your friends. Stay curious, keep learning, and always strive for continuous improvement.

[End]

Hack Reactor能否讓你變得更聰明?

日常流程

每天早上,我在午夜12點醒來。我的鬧鐘幫我以成為軟體工程師的目標開始我的一天。作為香港的遠程學生,我比舊金山時間快16個小時。適應這種時差並不容易。課程材料只是增加了複雜性,涵蓋了遞迴、哈希表、偽經典繼承、骨幹和快速等主題。那麼,我從這個經驗中得到了什麼?

學習批判性思考

專業軟體工程師能創造出優秀的產品,不僅僅是因為他們具有出色的編碼技巧,更因為他們具備正確的思維方式。他們對特定框架有多熟練只是其中一個因素。他們也是快速而持久的學習者,有效且富有同理心的溝通者,並且是主動好奇的問題解決者。這些技能不能僅從書本或網上視頻中學習到;他們來自於實踐操作,觀察導師如何解決問題,並從導師身上學習。

從更有知識的同伴身上學習

這個編碼訓練營吸引了許多聰明的人,將它與其他學習平台區分開來。我經常問自己:"我是否足夠聰明以應對這個優秀的機構?"騙子症候群的感覺是真實的。與更聰明的人接觸有時會讓我感到害怕,讓我覺得自己不夠好。然而,它也促使我更樂意去犯錯、失敗,從而以更快的速度學習。

編碼能否讓我變得更聰明?

我認為確實能,而我們相信的往往會成為自我應驗的預言。與聰明的人共事提升了我的迎接挑戰和思考問題的方式。總有一種更好、更有效、更簡單的方法來做事。你周圍的人愈聰明,你就越有可能從他們身上學到,從而讓自己變得更聰明。

Testing with Mocha: Array Comparison

The Problem

While writing a Mocha test suite for array comparison, I encountered an issue. Here is the test suite:

describe("Array comparison", function () {
  "use strict"
  it("should return true if two arrays have the same values", function () {
    var myArray = ["a", "b", "c"]
    expect(myArray).to.equal(["a", "b", "c"])
  })
})

Contrary to my expectations, this test fails, producing the following error:

AssertionError: expected ['a', 'b', 'c'] to equal ['a', 'b', 'c']

My Explanation

Why don't arrays compare like other values? It's because the typeof array is an object. In Mocha, to.equal doesn't indicate that the operands are semantically equal; rather, it checks if they refer to the exact same object. In other words, the test fails because myArray is not the exact same object as ['a', 'b', 'c'].

Possible Solutions

  1. Use .eql for "loose equality" to deeply compare values.
  2. Use .deep.equal, which tests whether the operands are equivalent but not necessarily the same object.
  3. Check .members in the array instead.
  4. Convert the array to a string and then compare.

References


I hope this revised version better communicates your insights and solutions.

Testing with Mocha: Array Comparison

Hello and welcome to Continuous Improvement, the podcast where we explore common development issues and find solutions for them. I'm your host, Victor, and today we're going to talk about an interesting problem that I encountered while writing a Mocha test suite for array comparison.

So, I had this simple test suite for array comparison that should return true if two arrays have the same values. Here's the code:

describe('Array comparison', function () {
  'use strict';
  it('should return true if two arrays have the same values', function () {
    var myArray = ['a', 'b', 'c'];
    expect(myArray).to.equal(['a', 'b', 'c']);
  });
});

Now, you would expect this test to pass, right? After all, the arrays have the same values. But, to my surprise, the test failed with an AssertionError. Here's the error message:

AssertionError: expected ['a', 'b', 'c'] to equal ['a', 'b', 'c']

So, I started digging into the problem and here's what I found. Arrays in JavaScript are considered as objects in terms of their data type. That's why when we use the to.equal assertion in Mocha, it checks if the two operands are the exact same object, not just semantically equal.

Understanding this, I came up with a few possible solutions. The first one is to use .eql, which stands for "loose equality". This allows us to deeply compare the values of the arrays. Another option is to use .deep.equal, which checks if the operands are equivalent but not necessarily the same object. Alternatively, you can also check the .members in the array instead. And lastly, you can convert the array to a string and then compare.

Now, if you're interested in exploring these solutions further, I highly recommend checking out the references I found helpful. They are the ChaiJS BDD API Arguments Section and the ChaiJS BDD API Members Section.

And that concludes today's episode of Continuous Improvement. I hope you found this discussion insightful and helpful for your own development journey. If you have any topics or issues you'd like me to cover in future episodes, feel free to reach out to me.

Thank you for listening, and until next time, keep improving!