워크스페이스 디테일에서 현재 이 워크스페이스에 업로드 된 모든 파일을 가져오기 위해
쿼리빌더를 사용하여 모든 파일을 조회
// 워크스페이스에 업로드된 모든 파일 조회
async getAllFiles(workspaceId: number): Promise<File[]> {
const workspace = await this.workspaceRepository
.createQueryBuilder('workspace')
.innerJoinAndSelect('workspace.boards', 'boards')
.innerJoinAndSelect('boards.board_columns', 'board_columns')
.innerJoinAndSelect('board_columns.cards', 'cards')
.where('workspace.id = :workspaceId', { workspaceId })
.select([
'cards.id',
'cards.file_original_name',
'cards.file_url',
'cards.file_size',
'cards.created_at',
'cards.updated_at',
])
.getRawMany();
return workspace;
}
필요한 컬럼들을 선택해 준 뒤 프론트에서 요청 시 데이터가 넘어가는 지 확인
원하는 정보가 넘어온 것을 확인하고 하나의 카드에 여러개의 파일이 존재하는 경우도 있으므로
다음과 같이 코드를 작성
// 전체파일 조회
async function getAllFiles() {
try {
await $.ajax({
method: 'GET',
url: `/workspaces/${workspaceId}/getFiles`,
beforeSend: function (xhr) {
xhr.setRequestHeader('Content-type', 'application/json');
xhr.setRequestHeader('authorization', `Bearer ${accessToken}`);
},
success: async (data) => {
let result = '';
data.forEach((file) => {
const fileOriginalName = file.cards_file_original_name;
const fileUrl = file.cards_file_url;
const fileSize = file.cards_file_size;
let fileNames = [];
let fileSizes = [];
let fileUrls = [];
if (typeof fileOriginalName === 'string') {
try {
fileNames = JSON.parse(fileOriginalName);
} catch (err) {
fileNames = [fileOriginalName];
}
} else {
fileNames = fileOriginalName;
}
if (typeof fileSize === 'string') {
try {
fileSizes = JSON.parse(fileSize);
} catch (err) {
fileSizes = [parseInt(fileSize)];
}
} else {
fileSizes = fileSize;
}
if (typeof fileUrl === 'string') {
try {
fileUrls = JSON.parse(fileUrl);
} catch (err) {
fileUrls = [fileUrl];
}
} else {
fileUrls = fileUrl;
}
if (Array.isArray(fileNames) && fileNames.length > 0) {
for (let i = 0; i < fileNames.length; i++) {
const fileName = fileNames[i];
const fileUrl = fileUrls[i];
const imgSrc = getImgSource(fileName);
const fileSize = getFileSize(fileSizes[i]);
result += printFilesHtml(fileName, imgSrc, fileSize, fileUrl);
}
} else if (typeof fileOriginalName === 'string') {
const fileName = fileOriginalName.replace(/"/g, '');
const fileSize = getFileSize(fileSizes);
const fileUrl = fileUrls;
const imgSrc = getImgSource(fileName);
result += printFilesHtml(fileName, imgSrc, fileSize, fileUrl);
}
});
const totalSize = getTotalFileSize(data);
const storage = await printStorageSize(totalSize);
printStorage.innerHTML = storage;
printFiles.innerHTML = result;
},
});
} catch (err) {
console.error(err);
}
}
배열이 문자열로 넘어오는 형태기때문에 문자열이라면 JSON형태로 파싱해주는 코드를 작성하고
파일의 아래 용량을 표현해주기위해 파일사이즈를 구하는 함수를 작성
// 파일 메가바이트로 변환
function getFileSize(fileSize) {
const fileSizeInMb = fileSize / (1024 * 1024);
return fileSizeInMb.toFixed(2);
}
확장자에 따라 붙여주는 이미지가 다르므로 확장자 구분 함수도 작성
// 파일의 확장자 분류
function getImgSource(fileName) {
const extension = fileName.split('.').pop().toLowerCase();
const fileExtension = extension.replace(/"/g, '');
let imgSrc = '';
switch (fileExtension) {
case 'jpg':
case 'jpeg':
imgSrc = './assets/img/jpg@2x.png';
break;
case 'png':
imgSrc = './assets/img/png@2x.png';
break;
case 'zip':
imgSrc = './assets/img/zip@2x.png';
break;
case 'pdf':
imgSrc = './assets/img/pdf@2x.png';
break;
case 'psd':
imgSrc = './assets/img/psd@2x.png';
break;
default:
imgSrc = './assets/img/document.png';
break;
}
return imgSrc;
}
출력결과
중간의 []빈 파일은 카드 수정 시 파일을 변경하지 않으면 기존파일이 그대로 들어있어야 하는데 빈값으로 변경되는 현상이 있어서 수정필요
파일출력의 구현이 끝났으면 파일 용량을 계산해줘야 하므로 getAllFiles()로 불러왔던 파일사이즈를 활용하여 전쳬용량을 계산
// 파일 전체용량 계산
function getTotalFileSize(files) {
let totalSize = 0;
for (const file of files) {
const fileSize = file.cards_file_size;
if (typeof fileSize === 'string') {
const sizes = JSON.parse(fileSize);
if (Array.isArray(sizes)) {
for (const size of sizes) {
totalSize += parseInt(size, 10) || 0;
}
} else {
totalSize += parseInt(sizes, 10) || 0;
}
} else if (typeof fileSize === 'number') {
totalSize += fileSize;
}
}
const totalSizeInMb = totalSize / (1024 * 1024);
return totalSizeInMb.toFixed(2);
}
무료버전의 제한용량이 100mb이므로 mb단위로 변환, parseInt는 10진수로 고정을 해주고 여기서 합산된 사이즈를 printStorageSize()로 보내줌
// 워크스페이스 용량 조회
async function printStorageSize(totalSize) {
try {
const results = await $.ajax({
method: 'GET',
url: `/workspaces/${workspaceId}`,
beforeSend: function (xhr) {
xhr.setRequestHeader('Content-type', 'application/json');
xhr.setRequestHeader('authorization', `Bearer ${accessToken}`);
},
});
const { data } = results;
const totalSizeInGb = (totalSize / 1024).toFixed(2);
const usagePercentageGb = ((totalSizeInGb / 10) * 100).toFixed(0);
const usagePercentageMb = ((totalSize / 100) * 100).toFixed(0);
if (data.memberships.length) {
return `<div class="user-group-progress-bar">
<p>워크스페이스 사용량</p>
<div class="progress-wrap d-flex align-items-center mb-0">
<div class="progress">
<div
class="progress-bar bg-success"
role="progressbar"
style="width: ${usagePercentageGb}%"
aria-valuenow="${usagePercentageGb}"
aria-valuemin="0"
aria-valuemax="100"
></div>
</div>
<span class="progress-percentage">${usagePercentageGb}%</span>
</div>
<span class="">10GB 중 ${totalSizeInGb}GB 사용</span>
</div>`;
} else {
return `<div class="user-group-progress-bar">
<p>워크스페이스 사용량</p>
<div class="progress-wrap d-flex align-items-center mb-0">
<div class="progress">
<div
class="progress-bar bg-success"
role="progressbar"
style="width: ${usagePercentageMb}&"
aria-valuenow="${usagePercentageMb}"
aria-valuemin="0"
aria-valuemax="100"
></div>
</div>
<span class="progress-percentage">${usagePercentageMb}%</span>
</div>
<span class="">100MB 중 ${totalSize}MB 사용</span>
</div>`;
}
} catch (err) {
console.error(err);
}
}
멤버십을 가입한 워크스페이스라면 용량제한이 10gb이므로 gb로 사이즈를 변환해주고, 불러온 데이터 중 멤버십배열을 기준으로 있으면 10gb, 없으면 100mb로 html을 붙여줌
출력결과
무료버전인 경우
멤버십에 가입된 경우