Skip to content

Instantly share code, notes, and snippets.

@gnh1201
Last active September 21, 2025 11:18
Show Gist options
  • Save gnh1201/b70b14c94915468e4a3830bb32663adb to your computer and use it in GitHub Desktop.
Save gnh1201/b70b14c94915468e4a3830bb32663adb to your computer and use it in GitHub Desktop.
Directus WebSocket and File Upload realtime example
// 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