1

Hướng dẫn tạo ứng dụng chia sẻ ảnh thời gian thực với Nodejs (Phần 2)

Hôm nay mình sẽ tiếp tục hướng dẫn các bạn tạo một ứng dụng chia sẻ hình ảnh theo thời gian thực. Ví dụ bạn muốn muốn copy ảnh từ điện thoại qua máy tính nhưng không có cáp USB, hay đơn giản là bạn lười… cắm; Bạn sẽ vào trang web của ứng dụng (photobump.com – tên giả định), dùng điện thoại quét QR code trên trang web, và điện thoại sẽ mở ra tool để chọn hình gởi sang máy tính. Sau khi chọn hình trên điện thoại, máy tính sẽ nhanh chóng hiển thị hình ảnh vừa chọn lên mà không cần thao tác gì thêm. Hay bạn muốn chia sẻ ảnh cho bạn bè mình, chỉ cần cả hai có kết nối Internet, là bạn đã có thể chia sẻ lên bất cứ thiết bị nào, không cần cài đặt app, không cần có NFC hay bluetooth. Tới đây, có lẽ nhiều bạn đã từng gặp ứng dụng tương tự là PhotoBeamber trên Windows Phone và PhotoGleamer trên Android.

Với bài viết này, mình sẽ hướng dẫn các bạn tự tạo cho mình dịch vụ tương tự, sử dụng cùng 1 công nghệ y chang với các ứng dụng nổi tiếng ở trên, thậm chí còn vượt trội hơn khi không cần yêu cầu cài đặt app mà chỉ cần chạy trực tiếp trên web. Công nghệ chúng ta sử dụng ở đây là nền tảng Nodejs và Socket.io cũng như web framework Expressjs. Chúng ta sẽ sử dụng source code từ phần 1 (tại đây) để tiếp tục nâng cấp phiên bản.

Ở phần này, mình sẽ tập trung nói về ý tưởng cũng như những kỹ thuật chính mà không đi sâu vào giải thích chi tiết từng dòng code. Các bạn muốn demo hay nghiên cứu sau thì vào link github ở cuối bài nhé! Phần trước mình đã có code kỹ thuật để gởi ảnh thông qua web socket, phần này mình sẽ chủ yếu nói về việc định danh 1 kết nối/thiết bị để gởi dữ liệu chính xác đến thiết bị mong muốn.

Yêu cầu:

  • Đã đọc trước và theo dõi code share ảnh ở phần 1
  • Đã cài đặt Nodejs
  • Máy tính đã cắm điện

Làm thế nào để định danh mỗi client

Mỗi client kết nối vào server cần có 1 ID để định danh chính xác. Khi có ID, ta sẽ biết client nào muốn gởi data đến client nào, mà không gởi nhầm hay gởi đến toàn bộ kết nối. May mắn thay, với Socket.io, mỗi client socket kết nối vào server đều được gán một id sẵn dùng cho chúng ta. Chỉ cần gọi socket.id là lấy được id này. Nhưng ID của Socket.io là một chuỗi tới 106bit. Việc sử dụng chuỗi số này là không khả thi với người sử dụng, khi họ có nhu cầu chia sẻ ID của mình để bạn bè gởi ảnh đến. Mình sẽ dùng cách random ra 1 số tự nhiên 5 chữ số ( simpleCode ), và “binding” số này với socket id, thay vì dùng chuỗi ký tự loằng ngoằng 20 ký tự, giờ chúng ta chỉ dùng 5 chữ số.

Ở trên, mình tạo ra object bindingCodes  để lưu trữ toàn bộ các id kết nối vào server cùng với simpleCode  của nó. Ngay khi có kết nối, mình sẽ thêm 1 key là simpleCode chứa giá trị là id của socket. Do quy chuẩn của Javascript không cho phép đặt tên thuộc tính của đối tượng bắt đầu với số nên mình phải gắng 1 kí tự “c” ở đầu, kí hiệu cho “client”.

Đến khi ngắt kết nối, mình thực hiện delete simpleCode cùng socket id, để trả lại tự do cho số nguyên đang dùng làm simpleCode, các kết nối sau có thể sử dụng. Như vậy sẽ không lo lắng 5 chữ số thì không đủ phục vụ người dùng. (Chúng ta đang nói về 90.000 số nguyên đấy, mình chắc chắn rằng ứng dụng này không bao giờ có được 45.000 người dùng cùng lúc đâu. Nếu có thì mình quả là người nổi tiếng rồi.)

Làm thế nào để người dùng tương tác với ứng dụng dễ dàng nhất.

Từ tương tác ở đây có thể gây khó hiểu, cụ thể hơn đó là cách sử dụng dễ dàng nhất, đơn giản nhất, tiện lợi nhất mà phầm mềm cung cấp. Đem lại trải nghiệm thú vị cho người dùng. Ta có hai người dùng muốn share ảnh cho nhau, dĩ nhiên ta sẽ không làm ứng dụng kiểu nhập username, password nữa. Đó là một trải nghiệm tồi và cũ kỹ. Mình sẽ tạo ra trên màn hình của người nhận ảnh một ảnh QR code, chứa id chính là simpleCode ở trên ta dùng để định danh cho thiết bị vừa kết nối vào trang web. QR Code rất phổ biến trong thời nay,  thời đại thống trị của smartphone, bất kỳ chiếc smartphone nào có camera đều có thể đọc QR code một cách nhanh chóng và chính xác hơn cả mấy cái đầu đọc mã vạch ở siêu thị.

Làm thế nào để tạo ra QR code.

Để tạo ra ảnh QR code, ta cần package qr-image  của nodejs. trước tiên cần thêm tên gói vào package.json, chạy lại lệnh npm install  để cài thêm gói, và sau đó ta code như bên dưới:

Mục đích là khi ta đặt url có dạng “http://photobump.com/qrcode?text=Noi_Dung_Luu_Trong_QR_Code” vào 1 thẻ <img> , ta sẽ có được hình ảnh của 1 QR code với nội dung mong muốn. Ở đây, QR của chúng ta sẽ chứa 1 đường link truy cập đến 1 trang dành cho người gởi (sender), nơi người gởi có thể chọn ảnh và upload cho người nhận(receiver).

/public/js/receiver.script.js

Ở trên, do ta cần gởi nội dung là 1 URL trong nằm trong phần tham số http://photobump.com/qrcode?text= nên cần endcode để có thể gởi đầy đủ các ký tự :/?= lên server, sử dụng hàm build-in encodeURIComponent().

Đường link ta nén vào ảnh QR code là link có dạng http://photobump.com/send?to=12345, ta nạp sẵn ID của receiver vào link, để khi sender quét QR sẽ truy cập vào link có ID người nhận mà không cần nhập thêm bất cứ nội dung gì khác.

Làm thế nào để tạo trang cho sender và receiver?

Receiver – Trang chủ

Receiver đơn giản nhất, họ chỉ muốn nhận ảnh nên ta show QR code ngay trên trang chủ, với mục đích ưu tiên hàng đầu là chia sẻ ID của họ cho sender. Ta tạo template bằng Jade engine, xem file home.jade, template này đơn thuần tạo 1 trang HTML. Phần hình ảnh lúc nhận được từ sender và QR code sẽ dùng js để chèn vào. Jade engine là một nội dung khá lớn nên mình sẽ giải thích ở một bài khác. Phần này các bạn tạm chấp nhận và sử dụng code được cung cấp.

Sender – Tool upload ảnh

Trang này dùng file template  sender.jade, javascript là /public/js/sender.script.js. Trong template có 1 phần đặc biệt đó là truyền ID nhận được trên URL QR code, chèn vào trong trang để khi người dùng gởi hình, ta gởi kèm ID này để báo người nhận hình là ai. Để truyền biến từ Expressjs sang Jade template, gọi như sau:

Chú ý dòng gọi render(). Dùng key sendToID thì bên jade template, ta xuất ra bằng đúng key này. Xem dòng 10 trong /views/sender.jade sẽ thấy.

Sử dụng #{tên_biến} ta có thể xuất giá trị biến ra, như trong php ta dùng <?php echo $var ?>.

Làm thế nào để gởi ảnh từ sender sang receiver

Nếu bạn theo dõi phần 1 của bài viết, bạn sẽ hiểu rõ cách Javascript đọc file và truyền qua socket như thế nào. Chỉ có một chú ý đặc biệt, bình thường để gởi data, nhưng các tutorial thường gặp của Socket.io, người ta sẽ dùng socket.emit(). Nhưng với hàm này, ta broadcast tới tất cả các kết nối chứ không thể xác định chính xác người nhận. Thay vào đó, mình sử dụng io.to(socket_ID).emit(), hàm này sẽ chỉ định gởi data đến chính xác socket nào.

Ở trong đoạn code trên, mình lấy socket ID của receiver từ object bindingCodes bằng simpleCode (data.sendToID). Từ đó có thể emit chính xác đến màn hình máy nhận ảnh.

Làm thế nào…?

Vâng, sẽ còn nhiều câu hỏi lắm, vậy nên, mình nghĩ bạn bên download mã nguồn về, thực hiện config như hướng dẫn README.mc của dự án, và khởi động server lên để trải nghiệm.  Các bạn có thể download mã nguồn phiên bản V0.0.3 tương ứng với bài viết, tại https://github.com/nhtua/photoshare/releases/tag/0.0.3

Có bất kỳ câu hỏi nào, comment tại bài viết này hoặc tạo issue mới trên github nhé. Hoan nghênh cách bạn cùng fork và phát triển thêm các tính năng mới cho dự án.

Github của dự án: https://github.com/nhtua/photoshare

Bình luận với Facebook

Hoàng Tựa

Yêu thích lập trình web và tạo ra những thứ đẹp đẽ.

One Comment

Leave a Reply

Your email address will not be published. Required fields are marked *