Files
api/sample/dev/talk/js/module/attach.js
2025-07-02 21:55:07 +09:00

201 lines
6.4 KiB
JavaScript

import {talkEvent} from "http://devtalk.kospo.co.kr:3000/static/js/module/talkEvent.js";
import {global} from "http://devtalk.kospo.co.kr:3000/static/js/module/variable.js";
import Common from "http://devtalk.kospo.co.kr:3000/static/js/utils.js";
// 첨부파일 업로드 기능
function readFileAsDataURL(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = (e) => resolve(e.target.result);
reader.onerror = reject;
reader.readAsDataURL(file);
});
}
function loadImage(src) {
return new Promise((resolve, reject) => {
const img = new Image();
img.onload = () => resolve(img);
img.onerror = reject;
img.src = src;
});
}
const attachUpload = async (files) => {
checkAllowExt()
const chunkSize = 256 * 1024;
const key = talkEvent.generateUUID()
const workId = localStorage.getItem('workId');
const workNm = localStorage.getItem('workNm');
const talkId = localStorage.getItem(global.tabId);
if(talkId === null || workId === null) {
global.notifier.alert('통신 오류가 발생 했어요.<br/>새로고침 해주세요.')
return
}
const $files = [];
const insDate = Common.dateWithNanos(new Date());
let allFileSize = 0;
let isImage = true;
// mimtype 조회 이미지가 아닌 다른 파일이 있는지 확인
Array.from(files).forEach((fi) => {
if (!(fi.type.includes('image'))) {
isImage = false;
}
})
for (const file of Array.from(files)) {
const idx = Array.from(files).indexOf(file);
allFileSize += file.size;
const att = {
onm: file.name,
type: file.type,
sort: idx,
size: file.size,
}
// 파일 전체가 이미지 일 경우 해당 바이너리 정보 주입
if (isImage) {
// 1. 파일을 읽어서 DataURL로 변환 (FileReader 비동기 처리)
const dataURL = await readFileAsDataURL(file);
// 2. 변환된 DataURL을 이용해 이미지 로드 (Image 비동기 처리)
const img = await loadImage(dataURL);
// 3. 썸네일 용 dataURL 생성
const blob = await Common.cropImage(img, 105);
att.data = blob;
}
$files.push(att);
}
/*
첨부파일 업로드 설정 소켓 통신으로 해당 파일의 정보를 보내준다.
정보를 받는 대상자는 첨부파일 업로드 화면을 렌더링 한다.
이미지 같은 경우는 위 바이너리 정보로 썸네일 구성
이미지외 파일 혼합된 경우 파일 다운로드 화면 구성
(서버에서는 해당 내용으로 메시지를 저장한다.)
*/
talkEvent.attach(global.talkParams({
type: 'INIT',
talkId: talkId,
workId: workId,
workNm: workNm,
message: isImage ? "[사진]" : '[파일]',
insDate: insDate,
talkAttachDtos: $files,
attach: {
key: key,
totalSize: allFileSize
}
}))
setTimeout(attachStart, 300)
function checkAllowExt() {
const allow = ["jpg", "jpeg", "gif", "png", "bmp",
"xls", "xlsx", "csv", "pdf", "hwp", "doc", "docx", "ppt", "pptx", "txt",
"zip", "egg",
"mp4"]
files = Array.from(files).filter((file) => {
const fileExt = file.name.toLowerCase().substr(file.name.toLowerCase().lastIndexOf('.') + 1)
return allow.join(',').includes(fileExt)
})
}
function attachStart() {
if (files.length !== 0) {
Array.from(files).forEach((file, idx) => {
const vnm = Common.getAttachVnm(new Date(), global.tabId)
console.log(idx, vnm)
let offset = 0;
/*
각파일 정보를 전송
(서버에서는 메시지 첨부파일을 저장한다.)
*/
talkEvent.attach(global.talkParams({
type: 'START',
talkId: talkId,
workId: workId,
workNm: workNm,
insDate: insDate,
attach: {
key: key,
onm: file.name,
vnm: vnm,
size: file.size,
type: file.type,
sort: idx,
totalSize: allFileSize
}
}))
readAndSEndChunk(file, idx, offset, vnm)
})
}
}
let progressSize = 0;
function readAndSEndChunk(file, idx, offset, vnm) {
const reader = new FileReader();
reader.onload = (e) => {
const chunk = reader.result;
/*
파일의 바이너리 정보를 chunkSize 256kb 로 잘라서 전송한다.
받는 대상자는 해당 첨부파일의 진행률을 돌려받는다.
*/
talkEvent.attach(global.talkParams({
type: 'PROGRESS',
talkId: talkId,
workId: workId,
workNm: workNm,
insDate: insDate,
attach: {
key: key,
onm: file.name,
sort: idx,
vnm: vnm,
totalSize: allFileSize,
size: progressSize,
data: Array.from(new Uint8Array(chunk))
},
}))
progressSize += chunk.byteLength;
offset += chunk.byteLength;
if (offset < file.size) {
Common.sleep(100).then(() => {
readAndSEndChunk(file, idx, offset, vnm)
})
} else {
/*
파일 전송 완료 메시지
*/
talkEvent.attach(global.talkParams({
type: 'END',
talkId: talkId,
workId: workId,
workNm: workNm,
insDate: insDate,
attach: {
onm: file.name,
vnm: vnm,
key: key,
},
}))
}
}
const slice = file.slice(offset, offset + chunkSize);
reader.readAsArrayBuffer(slice)
}
}
export {attachUpload}