Last active
September 21, 2025 11:18
-
-
Save gnh1201/b70b14c94915468e4a3830bb32663adb to your computer and use it in GitHub Desktop.
Directus WebSocket and File Upload realtime example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // Directus + WebSocket + File Upload + Realtime + Jquery example | |
| // Namhyeon Go <[email protected]> | |
| const CommentWs = (function() { | |
| const ws_url = "wss://mydata.tld/websocket"; // websocket server url | |
| const fs_url = "https://mydata.tld/files"; | |
| const download_url = "https://mydata.tld/assets"; | |
| const access_token = ""; // authentication token | |
| const collection = "collection_name"; // collection (data store) name | |
| let last_fetched_time = new Date(0); // last fetched time | |
| let last_part_id = ""; | |
| let last_modeling_id = ""; | |
| // connect | |
| const connection = new WebSocket(ws_url); | |
| connection.addEventListener("open", function() { | |
| console.log({ | |
| event: "onopen" | |
| }); | |
| connection.send(JSON.stringify({ | |
| type: "auth", | |
| access_token | |
| })); | |
| }); | |
| connection.addEventListener("message", function(message) { | |
| const data = JSON.parse(message.data); | |
| console.log({ | |
| event: "onmessage", | |
| data: data | |
| }); | |
| if (data.type === "ping") { | |
| connection.send(JSON.stringify({ | |
| type: "pong" | |
| })); | |
| } | |
| messageCallback(data.data); | |
| }); | |
| function formatDate(date) { | |
| function pad(n) { return n < 10 ? '0' + n : n; } | |
| return date.getFullYear() + '-' + | |
| pad(date.getMonth() + 1) + '-' + | |
| pad(date.getDate()) + ' ' + | |
| pad(date.getHours()) + ':' + | |
| pad(date.getMinutes()) + ':' + | |
| pad(date.getSeconds()); | |
| } | |
| function isImageFile(filename) { | |
| return /\.(jpe?g|png|gif|bmp|webp|svg)$/i.test(filename); | |
| } | |
| function subscribe() { | |
| const menu_id = document.querySelector("#menu_id").value; | |
| const company_id = document.querySelector("#companyId").value; | |
| const part_id = document.querySelector("#part_id").value; | |
| const modeling_id = document.querySelector("#modelingId").value; | |
| if (part_id !== last_part_id || modeling_id !== last_modeling_id) { | |
| last_fetched_time = new Date(0); | |
| $("#replyMessageList").empty(); | |
| } | |
| connection.send(JSON.stringify({ | |
| type: "subscribe", | |
| collection, | |
| query: { | |
| fields: ["*"], | |
| filter: { | |
| menu_id: { | |
| "_eq": menu_id | |
| }, | |
| part_id: { | |
| "_eq": part_id | |
| }, | |
| modeling_id: { | |
| "_eq": modeling_id | |
| }, | |
| date_created: { | |
| "_gt": formatDate(last_fetched_time) | |
| } | |
| } | |
| } | |
| })); | |
| last_fetched_time = new Date(); | |
| last_part_id = part_id; | |
| last_modeling_id = modeling_id; | |
| } | |
| function write(message, file_id) { | |
| const menu_id = document.querySelector("#menu_id").value; | |
| const part_id = document.querySelector("#part_id").value; | |
| const modeling_id = document.querySelector("#modelingId").value; | |
| const member_id = document.querySelector("#mId").value; | |
| const company_id = document.querySelector("#companyId").value; | |
| const attached_file = file_id || null; | |
| connection.send(JSON.stringify({ | |
| type: "items", | |
| collection: collection, | |
| action: "create", | |
| data: { | |
| content: message, | |
| attached_file: attached_file, | |
| menu_id: menu_id, | |
| part_id: part_id, | |
| modeling_id: modeling_id, | |
| member_id: member_id, | |
| company_id: company_id | |
| } | |
| })); | |
| } | |
| function messageCallback(items) { | |
| const part_id = document.querySelector("#part_id").value; | |
| const modeling_id = document.querySelector("#modelingId").value; | |
| if (part_id !== last_part_id || modeling_id !== last_modeling_id) { | |
| return; | |
| } | |
| if (!items || !(items instanceof Array)) return; | |
| const replyMessageList = $("#replyMessageList"); | |
| items.forEach(function(item) { | |
| let createdDate = item.date_created; | |
| if (!item.attached_file) { | |
| replyMessageList.append("<li>" + item.content + "</li>"); | |
| } else { | |
| if (isImageFile(item.content)) { | |
| replyMessageList.append("<li><img src='" + (download_url + '/' + item.attached_file + '?key=system-small-cover') + "' alt='preview'></li>"); | |
| } | |
| replyMessageList.append("<li><a href='" + (download_url + '/' + item.attached_file) + "' target='_blank'>" + item.content + "</a></li>"); | |
| } | |
| }); | |
| } | |
| async function uploadFile(file) { | |
| const formData = new FormData(); | |
| formData.append("file", file); | |
| formData.append("filename_download", file.name); | |
| formData.append("title", file.name); | |
| const res = await fetch(fs_url, { | |
| method: "POST", | |
| headers: { | |
| Authorization: "Bearer " + access_token, | |
| }, | |
| body: formData, | |
| }); | |
| const result = await res.json(); | |
| console.log("Uploaded File ID:", result.data.id); | |
| return result.data.id; | |
| } | |
| return { | |
| subscribe, | |
| write, | |
| uploadFile | |
| }; | |
| })(); | |
| setInterval(CommentWs.subscribe, 1000); | |
| $("#btnMessageSend").click(function() { | |
| const messageInput = $("#messageInput"); | |
| let message = messageInput.val(); | |
| //alert(message); | |
| CommentWs.write(message); | |
| // clear | |
| messageInput.val(""); | |
| //alert("done"); | |
| }); | |
| // btnFileSend | |
| $("#btnFileSend").click(function() { | |
| (async function(input) { | |
| input.type = "file"; | |
| input.accept = "*/*"; | |
| input.addEventListener("change", async (e) => { | |
| const file = e.target.files[0]; | |
| if (!file) return; | |
| try { | |
| const file_id = await CommentWs.uploadFile(file); | |
| CommentWs.write("file attached: " + file.name, file_id); | |
| } finally { | |
| input.remove(); | |
| } | |
| }); | |
| input.click(); | |
| })(document.createElement("input")); | |
| // Directus: https://directus.io/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment