Ver código fonte

update 2024-06-11

junggilpark 1 ano atrás
pai
commit
46bce97d86
2 arquivos alterados com 581 adições e 411 exclusões
  1. 326 295
      src/app.js
  2. 255 116
      src/views/hello.html

+ 326 - 295
src/app.js

@@ -49,6 +49,7 @@ const cca = new msal.ConfidentialClientApplication(msalConfig);
 
 const {Document, Packer, Paragraph, TextRun} = require('docx');
 const messages = require('dote/src/messages.js');
+const { rejects } = require('assert');
 let WebSocketServer = require('websocket').server;
 // const redirectUri = 'https://localhost:53000/redirect';
 const redirectUri = 'https://localhost:53000/redirect';
@@ -372,7 +373,7 @@ serverApp.post('/api/makeFolder',
         }
         else {
           resultObj.message = "생성할 폴더 경로를 찾을 수 없습니다.";
-        }
+        } 
       }
       catch(error) {
         resultObj.message = "폴더 생성 중 오류가 발생하였습니다.<br>" + getErrorMessage(error);
@@ -381,7 +382,7 @@ serverApp.post('/api/makeFolder',
       res.json(resultObj);
 });
 
-function getErrorMessage(error) {
+function getErrorMessage(error) {   
   let errorText = "";
   if (error.response && error.response.status && error.response.statusText && error.response.data  && error.response.data.error) {
     // console.log(error.response);
@@ -393,8 +394,8 @@ function getErrorMessage(error) {
   else {
     console.log('================================ Error =====================================')
     console.log(error);
-    errorText = error;
-  }
+    errorText = error; 
+  } 
   return errorText;
 }
 
@@ -664,153 +665,79 @@ serverApp.post('/api/check-name',
       }
 });
 
-async function uploadDrive(options, folder, siteId, path, res) {
+async function uploadDrive(options, folder, siteId, path) {
   const startTime = new Date();
-  if (folder) {
-    if (!Array.isArray(folder)) {
-      folder = [folder];
-    }
-    for (let item of folder) {
-      const fileInfo = JSON.parse(item);
+  const resultObj = {
+    success : 'S',
+    message : '',
+  }
 
-      const param = {
-        name: fileInfo.name,
-        folder: {},
-        '@microsoft.graph.conflictBehavior': 'rename'
-      };
+  if (!Array.isArray(folder)) {
+    folder = [folder];
+  }
+  for (let item of folder) {
+    const fileInfo = JSON.parse(item);
 
-      let folderPath = '';
-      if (fileInfo.path) {
-        folderPath = fileInfo.path; 
-        if (!path.includes(':')) {
-          folderPath = ":" + folderPath;
-        }
-      }
-      let uri = endPoint + "/sites/"+ siteId + path + folderPath;
-      try {
-        const result = await new Promise (async (resolve, reject)=>{
-          try {
-            const sitesInfo = await axios.get(uri, options);
-            resolve(sitesInfo.data);
-          }
-          catch(error) {
-            if (error.response) {
-              reject(error.response);
-            }
-            else {
-              reject(error);
-            }
-          }
-        }).then(async (result)=>{
-          return await new Promise(async (resolve, reject)=>{
-            try {
-              const uploadFolder = await axios.post(endPoint + "/sites/"+ siteId +"/drive/items/" + result.id +"/children", param, options);
-              resolve(uploadFolder.data);
-            }
-            catch(error){
-              if (error.response) {
-                reject(error.response);
-              }
-              else {
-                reject(error);
-              }
-            }
-          })
-        })
-      }
-      catch(error) {
-        return res.json({success:'F', message: '요청하신 파일 업로드 중 오류가 발생하였습니다.<br>' + getErrorMessage(error)});
+    const param = {
+      name: fileInfo.name,
+      folder: {},
+      // '@microsoft.graph.conflictBehavior': 'rename'
+    };
+
+    let folderPath = '';
+    if (fileInfo.path) {
+      folderPath = fileInfo.path; 
+      if (!path.includes(':')) {
+        folderPath = ":" + folderPath;
       }
     }
-    const makeFolderTime = new Date();
+    let uri = endPoint + "/sites/"+ siteId + path + folderPath;
+    const result = await new Promise (async (resolve, reject)=>{
+        axios.get(uri, options).then((sitesInfo)=>{
+          resolve(sitesInfo.data);
+        })
+        .catch((error)=>{
+          reject(error);
+        });
+    })
+    .then(async (result)=>{
+      return await new Promise(async (resolve, reject)=>{ 
+          axios.post(endPoint + "/sites/"+ siteId +"/drive/items/" + result.id +"/children", param, options)
+              .then((uploadFolder)=>{
+                resolve(uploadFolder.data);
+              })
+              .catch((error)=>{
+                reject(error);
+              });
+      });
+    })
+    .catch((error)=>{
+      return {success:'F', message: '요청하신 파일 업로드 중 오류가 발생하였습니다.<br>' + getErrorMessage(error)};
+    });
 
-    console.log('폴더 시작 시간 :', startTime.toLocaleString(), ', 폴더 종료 시간 :', makeFolderTime.toLocaleString(), ', 소요 시간 :', timeCheck(startTime, makeFolderTime));
+    if (result.success === 'F') {
+      return result;
+    }
   }
+  const makeFolderTime = new Date();
+
+  console.log('폴더 시작 시간 :', startTime.toLocaleString(), ', 폴더 종료 시간 :', makeFolderTime.toLocaleString(), ', 소요 시간 :', timeCheck(startTime, makeFolderTime));
+  return resultObj;
 }
 
 serverApp.post('/api/upload', upload.array('file'),
-  // isAuthenticated,
-  // isAccessTokens,
   async (req, res, next)=>{
     const startTime = new Date();
     const files = req.files;
-    let {siteId, path, folder, file_path} = req.body;
+    let {siteId, path, folder, file_path} = req.body; 
     if (siteId && path) {
       const options = getOptions(req.session.accessToken);
-      // const folderResult = await makeFolder(options, folder, siteId, path, file_path, files, req.session);
-      // console.log(folderResult);
-      // return res.json(folderResult);
-      // if (folder) {
-      //     if (!Array.isArray(folder)) {
-      //       folder = [folder];
-      //     }
-      //     for (let item of folder) {
-      //       const fileInfo = JSON.parse(item);
-
-      //       const param = {
-      //         name: fileInfo.name,
-      //         folder: {},
-      //         '@microsoft.graph.conflictBehavior': 'rename'
-      //       };
-
-      //       let folderPath = '';
-      //       if (fileInfo.path) {
-      //         folderPath = fileInfo.path; 
-      //         if (!path.includes(':')) {
-      //           folderPath = ":" + folderPath;
-      //         }
-      //       }
-      //       let uri = endPoint + "/sites/"+ siteId + path + folderPath;
-      //       try {
-      //         const result = await new Promise (async (resolve, reject)=>{
-      //           try {
-      //             const sitesInfo = await axios.get(uri, options);
-      //             resolve(sitesInfo.data);
-      //           }
-      //           catch(error) {
-      //             if (error.response) {
-      //               reject(error.response);
-      //             }
-      //             else {
-      //               reject(error);
-      //             }
-      //           }
-      //         }).then(async (result)=>{
-      //           return await new Promise(async (resolve, reject)=>{
-      //             try {
-      //               const uploadFolder = await axios.post(endPoint + "/sites/"+ siteId +"/drive/items/" + result.id +"/children", param, options);
-      //               resolve(uploadFolder.data);
-      //             }
-      //             catch(error){
-      //               if (error.response) {
-      //                 reject(error.response);
-      //               }
-      //               else {
-      //                 reject(error);
-      //               }
-      //             }
-      //           })
-      //         }).catch((error)=>{
-      //           console.log(error);
-      //         })
-      //       }
-      //       catch(error) {
-      //         return res.json({success:'F', message: '요청하신 파일 업로드 중 오류가 발생하였습니다.<br>' + getErrorMessage(error)});
-      //       }
-      //     }
-      //     const makeFolderTime = new Date();
-
-      //     let betweenTime = makeFolderTime - startTime;
-      //     if (betweenTime > 60000) {
-      //       betweenTime = (betweenTime/1000/60) + ' 분';
-      //     }
-      //     else {
-      //       betweenTime = (betweenTime/1000) + ' 초';
-      //     }
-      //       console.log('폴더 시작 시간 :', startTime.toLocaleString(), ', 폴더 종료 시간 :', makeFolderTime.toLocaleString(), ', 소요 시간 :', betweenTime);
-      //   }
-      await uploadDrive(options, folder, siteId, path, res);
-
+      if (folder){
+        const uploadDriveResult = await uploadDrive(options, folder, siteId, path);
+        if (uploadDriveResult.success === 'F') {
+          return res.json(uploadDriveResult);
+        }
+      }
         const promiseArray = [];
         const labelPromiseArray = [];
         const fileWriteArray = [];
@@ -1080,150 +1007,209 @@ serverApp.post('/api/download',
   // isAuthenticated,
   // isAccessTokens,
   async (req, res, next)=>{
-    let startTime = new Date();
-    if (req.body) {
+    try {
+      let startTime = new Date();
       const {siteId, path, fileIds, zipName} = req.body;
       if (siteId && path && fileIds) {
-        const options = getOptions(req.session.accessToken);
-        const arr = JSON.parse(fileIds);
-        if (arr.length === 1) {
-          const sitesInfo = await axios.get(endPoint + "/sites/"+ siteId + "/drive/items/" + arr[0], options);
-          if (sitesInfo && sitesInfo.data) {
-            const data = sitesInfo.data;
-            if (data.folder) {
-              const folderObj = await getFolderItems(endPoint + "/sites/"+ siteId + "/drive/items/", arr, options, req.session);
-              const zip = new JSZIP();
-              if (folderObj) {
-                createZipFile(folderObj, zip);
-                const now = new Date();
-                const year = now.getFullYear().toString();
-                let month = now.getMonth() + 1;
-                if (month < 10) month = "0" + month;
-                let date = now.getDate();
-                if (date < 10) date = "0" + date;
-                zip.generateAsync({
-                  type: 'nodebuffer',
-                  mimeType: 'application/epub+zip',
-                  compression: 'DEFLATE',
-                  compressionOptions: {
-                    level: 9
-                  },
-                }).then((resZip)=>{
-                  const endTime = new Date();
-                  let betweenTime = endTime - startTime;
-                  if (betweenTime > 60000) {
-                    betweenTime = (betweenTime/1000/60) + ' 분';
-                  }
-                  else {
-                    betweenTime = (betweenTime/1000) + ' 초';       
-                  }
-                  console.log('시작 시간 :', startTime.toLocaleString(), ', 종료 시간 :', endTime.toLocaleString(), ', 소요 시간 :', betweenTime);
-                  return res.json({success: 'S', data: resZip, name: data.name + '_' + year + '-' + month + '-' + date + '.zip'});
-                })
-                .catch((error)=>{
-                  console.log(error);
-                  return res.json({success: 'F', message:'파일 다운로드 중 오류가 발생하였습니다.', error: error});
-                });
-              }
-            }
-            else {
-              const dataUrl = data['@microsoft.graph.downloadUrl'];
-              const response = await axios.get(dataUrl, {responseType: 'arraybuffer', headers: {
-                withCredentials:true,
-              },});
-
-              if (response.data) {
-                const file = Buffer.from(response.data, 'arraybuffer').toString('base64');
-                let decodeFile = null;
-                try {
-                  const param = {
-                    apiKey: gateWayKey,
-                    email : req.session.account.idTokenClaims.email,
-                    dispFileName: data.name,
-                    comment: "",
-                    fileData: file
-                  }
-                  
-                  const result = await axios.post(apiUrl + '/api/v1/stream/delete-label', param);
-                  if (result && result.data.statusCode === 200 && !result.data.result.errorCode) {
-                      decodeFile = result.data.result.fileData;
-                  }
-                  else {
-                      return res.json({message: '파일명 : ' +data.name + '<br>에러 : ' + result.data.result.errorMessage, success: 'F'});
-                  }
-                }
-                catch(error) {
-                  return res.json({message: '레이블 해제 중 오류가 발생하였습니다.<br>' + JSON.stringify(error.message), success: 'F'});
-                }
-                const endTime = new Date();
-                let betweenTime = endTime - startTime;
-                if (betweenTime > 60000) {
-                  betweenTime = (betweenTime/1000/60) + ' 분';
-                }
-                else {
-                  betweenTime = (betweenTime/1000) + ' 초';       
-                }
-                console.log('시작 시간 :', startTime.toLocaleString(), ', 종료 시간 :', endTime.toLocaleString(), ', 소요 시간 :', betweenTime);
-                return res.json({success: 'S', data: decodeFile, type: data.file.mimeType, name: data.name});
-              }
-              else {
-                return res.json({message:'파일 다운로드에 실패하였습니다.', success:'F'})
-              }
-            }
+          const options = getOptions(req.session.accessToken);
+          const arr = JSON.parse(fileIds);
+          const url = endPoint + "/sites/"+ siteId + "/drive/items/";
+          const zip = new JSZIP();
+          const downObj = await getFolderItems(url, arr, options, req.session);
+          const folderLength = downObj.folder.length;
+          const fileLength = downObj.files.length;
+
+          if (downObj && (folderLength > 1 || fileLength > 1 || (folderLength + fileLength) > 1)) {
+            createZipFile(downObj, zip);
+            const now = new Date();
+            const year = now.getFullYear().toString();
+            let month = now.getMonth() + 1;
+            if (month < 10) month = "0" + month;
+            let date = now.getDate();
+            if (date < 10) date = "0" + date;
+            zip.generateAsync({
+              type: 'nodebuffer',
+              mimeType: 'application/epub+zip',
+              compression: 'DEFLATE',
+              compressionOptions: {
+                level: 9
+              },
+            }).then((resZip)=>{
+              const endTime = new Date();
+              console.log('시작 시간 :', startTime.toLocaleString(), ', 종료 시간 :', endTime.toLocaleString(), ', 소요 시간 :', timeCheck(startTime, endTime));
+              return res.json({success: 'S', data: resZip, name: zipName + '_' + year + '-' + month + '-' + date + '.zip'});
+            })
+            .catch((error)=>{
+              console.log(error);
+              return res.json({success: 'F', message:'파일 다운로드 중 오류가 발생하였습니다.', error: error});
+            });
+          }
+          else if (downObj.folder.length > 0 && downObj.files.length === 0) {
+            return res.json({success:'F', messages:'폴더안에 파일이 존재하지 않습니다.'})
+          }
+          else if (downObj.files.length === 1){
+            const data = downObj.files[0];
+            console.log(data);
+            return res.json({success: 'S', data: data.data, name: data.name})
           }
-        }
-        else {
-            try {
-              const url = endPoint + "/sites/"+ siteId + "/drive/items/";
-              const zip = new JSZIP();
-              const downObj = await getFolderItems(url, arr, options, req.session);
-              if (downObj) {
-                createZipFile(downObj, zip);
-                const now = new Date();
-                const year = now.getFullYear().toString();
-                let month = now.getMonth() + 1;
-                if (month < 10) month = "0" + month;
-                let date = now.getDate();
-                if (date < 10) date = "0" + date;
-                zip.generateAsync({
-                  type: 'nodebuffer',
-                  mimeType: 'application/epub+zip',
-                  compression: 'DEFLATE',
-                  compressionOptions: {
-                    level: 9
-                  },
-                }).then((resZip)=>{
-                  const endTime = new Date();
-                  let betweenTime = endTime - startTime;
-                  if (betweenTime > 60000) {
-                    betweenTime = (betweenTime/1000/60) + ' 분';
-                  }
-                  else {
-                    betweenTime = (betweenTime/1000) + ' 초';       
-                  }
-                  console.log('시작 시간 :', startTime.toLocaleString(), ', 종료 시간 :', endTime.toLocaleString(), ', 소요 시간 :', betweenTime);
-                  return res.json({success: 'S', data: resZip, name: zipName + '_' + year + '-' + month + '-' + date + '.zip'});
-                })
-                .catch((error)=>{
-                  console.log(error);
-                  return res.json({success: 'F', message:'파일 다운로드 중 오류가 발생하였습니다.', error: error});
-                });
-              }
-            }
-            catch(err) {
-              // console.log(sitesInfo.data);
-              console.log(err);
-            }
-          // }
-        }
       }
       else {
         return res.json({message:'다운로드 파일 정보를 확인 할 수 없습니다.', success:'F'})
       }
     }
+    catch(error) {
+      return res.json({success: 'F', message:'파일 다운로드 중 오류가 발생하였습니다.<br>'+ getErrorMessage(error)});
+    }
   }
 );
 
+// serverApp.post('/api/download',
+//   // isAuthenticated,
+//   // isAccessTokens,
+//   async (req, res, next)=>{
+//     try {
+//       let startTime = new Date();
+//       if (req.body) { 
+//         const {siteId, path, fileIds, zipName} = req.body;
+//         if (siteId && path && fileIds) {
+//           const options = getOptions(req.session.accessToken);
+//           const arr = JSON.parse(fileIds);
+//           if (arr.length === 1) {
+//             const sitesInfo = await axios.get(endPoint + "/sites/"+ siteId + "/drive/items/" + arr[0], options);
+//             if (sitesInfo && sitesInfo.data) {
+//               const data = sitesInfo.data;
+//               if (data.folder) {
+//                   const folderObj = await getFolderItems(endPoint + "/sites/"+ siteId + "/drive/items/", arr, options, req.session);
+//                   // return res.json({success: 'F', message:'test', obj : folderObj});
+//                   const zip = new JSZIP();
+//                   if (folderObj) {
+//                     createZipFile(folderObj, zip);
+//                     const now = new Date();
+//                     const year = now.getFullYear().toString();
+//                     let month = now.getMonth() + 1;
+//                     if (month < 10) month = "0" + month;
+//                     let date = now.getDate();
+//                     if (date < 10) date = "0" + date;
+//                     zip.generateAsync({
+//                       type: 'nodebuffer',
+//                       mimeType: 'application/epub+zip',
+//                       compression: 'DEFLATE',
+//                       compressionOptions: {
+//                         level: 9
+//                       },
+//                     }).then((resZip)=>{
+//                       const endTime = new Date();
+//                       let betweenTime = endTime - startTime;
+//                       if (betweenTime > 60000) {
+//                         betweenTime = (betweenTime/1000/60) + ' 분';
+//                       }
+//                       else { 
+//                         betweenTime = (betweenTime/1000) + ' 초';       
+//                       }
+//                       console.log('시작 시간 :', startTime.toLocaleString(), ', 종료 시간 :', endTime.toLocaleString(), ', 소요 시간 :', betweenTime);
+//                       return res.json({success: 'S', data: resZip, name: data.name + '_' + year + '-' + month + '-' + date + '.zip'});
+//                     })
+//                     .catch((error)=>{
+//                       console.log(error);
+//                       return res.json({success: 'F', message:'파일 다운로드 중 오류가 발생하였습니다.', error: error});
+//                     });
+//                   }
+              
+//             }
+//             else {
+//               const dataUrl = data['@microsoft.graph.downloadUrl'];
+//               const response = await axios.get(dataUrl, {responseType: 'arraybuffer', headers: {
+//                 withCredentials:true,
+//               },});
+
+//               if (response.data) {
+//                 const file = Buffer.from(response.data, 'arraybuffer').toString('base64');
+//                 let decodeFile = null;
+//                 try {
+//                   const param = {
+//                     apiKey: gateWayKey,
+//                     email : req.session.account.idTokenClaims.email,
+//                     dispFileName: data.name,
+//                     comment: "",
+//                     fileData: file
+//                   }
+                  
+//                   const result = await axios.post(apiUrl + '/api/v1/stream/delete-label', param);
+//                   if (result && result.data.statusCode === 200 && !result.data.result.errorCode) {
+//                       decodeFile = result.data.result.fileData;
+//                   }
+//                   else {
+//                       return res.json({message: '파일명 : ' +data.name + '<br>에러 : ' + result.data.result.errorMessage, success: 'F'});
+//                   }
+//                 }
+//                 catch(error) {
+//                   return res.json({message: '레이블 해제 중 오류가 발생하였습니다.<br>' + JSON.stringify(error.message), success: 'F'});
+//                 }
+//                 const endTime = new Date();
+//                 let betweenTime = endTime - startTime;
+//                 if (betweenTime > 60000) {
+//                   betweenTime = (betweenTime/1000/60) + ' 분';
+//                 }
+//                 else {
+//                   betweenTime = (betweenTime/1000) + ' 초';       
+//                 }
+//                 console.log('시작 시간 :', startTime.toLocaleString(), ', 종료 시간 :', endTime.toLocaleString(), ', 소요 시간 :', betweenTime);
+//                 return res.json({success: 'S', data: decodeFile, type: data.file.mimeType, name: data.name});
+//               }
+//               else {
+//                 return res.json({message:'파일 다운로드에 실패하였습니다.', success:'F'})
+//               }
+//             }
+//           }
+//         }
+//         else {
+//             try {
+//               const url = endPoint + "/sites/"+ siteId + "/drive/items/";
+//               const zip = new JSZIP();
+//               const downObj = await getFolderItems(url, arr, options, req.session);
+//               if (downObj) {
+//                 createZipFile(downObj, zip);
+//                 const now = new Date();
+//                 const year = now.getFullYear().toString();
+//                 let month = now.getMonth() + 1;
+//                 if (month < 10) month = "0" + month;
+//                 let date = now.getDate();
+//                 if (date < 10) date = "0" + date;
+//                 zip.generateAsync({
+//                   type: 'nodebuffer',
+//                   mimeType: 'application/epub+zip',
+//                   compression: 'DEFLATE',
+//                   compressionOptions: {
+//                     level: 9
+//                   },
+//                 }).then((resZip)=>{
+//                   const endTime = new Date();
+//                   console.log('시작 시간 :', startTime.toLocaleString(), ', 종료 시간 :', endTime.toLocaleString(), ', 소요 시간 :', timeCheck(startTime, endTime));
+//                   return res.json({success: 'S', data: resZip, name: zipName + '_' + year + '-' + month + '-' + date + '.zip'});
+//                 })
+//                 .catch((error)=>{
+//                   console.log(error);
+//                   return res.json({success: 'F', message:'파일 다운로드 중 오류가 발생하였습니다.', error: error});
+//                 });
+//               }
+//             }
+//             catch(err) {
+//               console.log(err);
+//               return res.json({success: 'F', message:'파일 다운로드 중 오류가 발생하였습니다.', error: getErrorMessage(err)});
+//             }
+//           }
+//         }
+//         else {
+//           return res.json({message:'다운로드 파일 정보를 확인 할 수 없습니다.', success:'F'})
+//         }
+//       }
+//     }
+//     catch(error) {
+//       return res.json({success: 'F', message:'파일 다운로드 중 오류가 발생하였습니다.<br>'+ getErrorMessage(error)});
+//     }
+//   }
+// );
+
 serverApp.post('/api/folderMove', async (req, res, next)=>{
   if (req.body) {
     const {id, name, siteId, driveId, text, moveSiteId, movePath} = req.body;
@@ -1328,13 +1314,13 @@ async function findSubFolder(data, movePath, moveSiteId, options) {
 
 function createZipFile(obj, zip) {
   
-  if (obj.files.length > 0) {
+  if (obj.files && obj.files.length > 0) {
     for (let file of obj.files) {
       zip.file(file.name, file.data, {base64: true});
     }
   }
 
-  if (obj.folder.length > 0) {
+  if (obj.folder && obj.folder.length > 0) {
     for (let folder of obj.folder) {
       zip.folder(folder.name);
       if (folder.subFolder) {
@@ -1345,46 +1331,89 @@ function createZipFile(obj, zip) {
 }
 
 async function getFolderItems(url, array, options, session) {
-  const files = [];
-  // let subFolder = [];
-  let folder = [];
-  
+  const files         = [];
+  const folder        = [];
+  const sitesInfoArr  = [];
+  const fileArr       = [];
+  const fileInfoArr   = [];
+
+  const folderCheckTime = new Date();
   for (let fileId of array) {
-    const sitesInfo = await axios.get(url + fileId, options);
-    const data = sitesInfo.data;
+    sitesInfoArr.push(axios.get(url + fileId, options));
+  }
+  const siteInfos = await Promise.all(sitesInfoArr).catch((error)=>{
+    console.log(error);
+  });
+
+  for (let site of siteInfos) {
+    const data = site.data;
     if (data) {
       if (data.folder) {
         const folderObj = {name : data.name, subFolder : []};
         if (data.folder.childCount) {
-          const itemsData = await axios.get(url + fileId + '/children', options);
+          const itemsData = await axios.get(url + data.id + '/children', options);
           if (itemsData && itemsData.data && itemsData.data.value.length > 0) {
             const idArr = [];
             for (let children of itemsData.data.value) {
               idArr.push(children.id);
             }
-            let result = await getFolderItems(url, idArr, options, session);
+
+            try {
+              let result = await getFolderItems(url, idArr, options, session);
+              folderObj.subFolder = result;
+            }
+            catch(error) {
+              if (error) {
+                throw error;
+              }
+            }
             // subFolder.push(result);
-            folderObj.subFolder = result;
           }
         }
         folder.push(folderObj);
       }
       else {
         const dataUrl = data['@microsoft.graph.downloadUrl'];
-        const response = await axios.get(dataUrl, {responseType: 'arraybuffer', headers: {
-          withCredentials:true,
-        },});
-
-        //암호화 해제
-        const result = await deleteLabelFile(session, data.name, response.data);
-        if (!result.error && result.fileData) {
-          files.push({name : data.name, data : result.fileData, type: data.file.mimeType});
-        }
-        // files.push({name : data.name, data : response.data, type: data.file.mimeType});
+        const fileOption = {responseType: 'arraybuffer', headers: { withCredentials : true }};
+        fileArr.push(axios.get(dataUrl, fileOption));
+        fileInfoArr.push(data);
       }
     }
   }
 
+  console.log('======================= folder check end ===============================')
+  console.log('folder check 소요시간 : ', timeCheck(folderCheckTime, new Date()));
+  console.log('======================= delete label start ===============================')
+  const fileDataArr = await Promise.all(fileArr);
+  
+  const deleteLabelTime = new Date();
+  const deleteLabelArr = [];
+  for (let idx in fileDataArr) {
+    let fileData = fileDataArr[idx].data;
+    const param = {
+      apiKey: gateWayKey,
+      email : session.account.idTokenClaims.email,
+      dispFileName: fileInfoArr[idx].name,
+      comment: "",
+      fileData: Buffer.from(fileData).toString('base64')
+    }
+    deleteLabelArr.push(axios.post(apiUrl + '/api/v1/stream/delete-label', param));
+  }
+
+  const deleteLabelFiles = await Promise.all(deleteLabelArr);
+  for (let idx in deleteLabelFiles) {
+    const fileObj = deleteLabelFiles[idx];
+    const data = fileObj.data;
+    if (data.success && !data.result.errorCode) {
+      files.push({name : fileInfoArr[idx].name, data: data.result.fileData});
+    }
+    else {
+      throw data.result.dispFileName + ' : ' + data.result.errorMessage;
+    }
+  }
+  console.log('======================= delete label end ===============================')
+  console.log('delete label 소요시간 : ',timeCheck(deleteLabelTime, new Date()));
+
   const resultObj = {
     folder : folder,
     files : files,
@@ -1762,14 +1791,16 @@ async function deleteLabelFile(session, name, file) {
     }
     else {
       resultObj.error = true;
-      resultObj.errorMessage = '파일명 : ' +data.name + '<br>에러 : ' + result.data.result.errorMessage;
+      resultObj.errorMessage = '파일명 : ' + name + '<br>에러 : ' + result.data.result.errorMessage;
+      console.log(result.data.result);
     }
-  }
-  catch(error) {
+  } 
+  catch(error) { 
+    console.log(error);
     resultObj.error = true;
     resultObj.errorMessage = '레이블 해제 중 오류가 발생하였습니다.<br>' + JSON.stringify(error.message);
   }
-  return resultObj;
+  return resultObj; 
 }
 
 function getOptions(token) {
@@ -1783,7 +1814,7 @@ function getOptions(token) {
 
 serverApp.use((err, req, res, next)=>{
   console.log(err.message);
-  console.log(err);
+  // console.log(err);
   console.log(res.statusCode);
   if (err) {
     res.status(400);

+ 255 - 116
src/views/hello.html

@@ -63,7 +63,7 @@
                     <div class="head-name" onclick="sorting('name')">이름</div>
                     <div class="head-size" onclick="sorting('size')">용량</div>
                     <div class="head-lastModifiedDateTime" onclick="sorting('lastModifiedDateTime')">수정된 날짜</div>
-                    <div class="head-lastModifiedBy.user.displayName" onclick="sorting('lastModifiedBy.user.displayName')">수정한 사람</div>
+                    <div class="head-lastModifiedBy" onclick="sorting('lastModifiedBy')">수정한 사람</div>
                     <div class="head-label" onclick="sorting('label')">민감도</div>
                 </div>
                 <div class="file-content"></div>
@@ -87,14 +87,6 @@
   });
 
   $(()=>{
-    const result = $.ajax({method: 'post', url: '/api/getPossibleExtList'
-      ,success : (res)=> {
-        console.log(res);
-      }
-      ,error : (err) => {
-        console.log(err);
-      }
-    });
     microsoftTeams.app.initialize().then(() => {
       getClientSideToken()
       .then((clientSideToken) => {
@@ -211,7 +203,8 @@
       }
       formData.append('file', file);
     }
-
+        
+    $(event.target).val("");
     upload(formData);
   }
 
@@ -256,7 +249,8 @@
         formData.append('file', file);
         let filePath = path;
 
-        formData.append(file.name + '_path', filePath);
+        // formData.append(file.name + '_path', filePath);
+        formData.append('file_path', filePath);
 
         if (!folders[path] && path.indexOf('/') >= 0) {
           let folderPath = "";
@@ -336,10 +330,8 @@
               modifyDate = modifyDate.substring(5, 7)+ '월 '+ modifyDate.substring(8, 10)+ '일';
             }
 
-            // let method = `findOneDriveChildrenItems('${obj.id}')`;(siteId, path, name, value)
             let method = `siteDriveChildrenItems('${obj.parentReference.siteId}','${obj.parentReference.path + '/' + obj.name}','${name}', null, event)`;
             if (obj.file) {
-              // method = `downloadItems('${obj['@microsoft.graph.downloadUrl']}', '${obj.name}', event)`;
               method = `openWebUrl('${obj.webUrl}', '${obj.name}', event)`;
             }
             str += `
@@ -435,11 +427,13 @@
                 str += `<div>편집</div>`;
               }
               const selectImage = $('section .file-content div.on').find('img');
-              if (checkCnt === 1 && 
+              if (
+                  checkCnt === 1     && 
                   selectImage.length && 
-                  isTeam === true &&
-                  selectImage.attr('src') !== '/static/images/folder.png'&&
-                  bindId) {
+                  isTeam === true    &&
+                  (selectImage.attr('src') !== '/static/images/folder.png') &&
+                  bindId
+                ) {
                 str += `<div onclick="addTabs('${bindId}')">탭으로 설정</div>`;
               }
               str += `<div onclick="download()">다운로드</div>
@@ -541,7 +535,7 @@
           },
           error : (error) => {
             console.log(error);
-            alertMessage('탭으로 설정', error.message, null, 'red');
+            alertMessage('탭으로 설정', '탭으로 설정 중 오류가 발생했습니다.<br>' + getErrorMessage(error), null, 'red');
           }
         })
       }
@@ -716,6 +710,7 @@
           },
           error: (error)=> {
             console.log(error);
+            alertMessage(alertTxt, '그룹 정보를 가져오는 중 오류가 발생했습니다.<br>' + getErrorMessage(error), null, 'red');
           }
       })
     }
@@ -847,6 +842,7 @@
                     },
                     error : (error) => {
                       console.log(error);
+                      alertMessage(alertTitle, alertTitle+' 중 오류가 발생했습니다.<br>' + getErrorMessage(error), null, 'red');
                     }
                   })
               }
@@ -1171,6 +1167,7 @@
                 },
                 error: (error)=> {
                   console.log(error);
+                  alertMessage('파일 삭제', '파일 삭제 작업 중 오류가 발생했습니다.<br>' + getErrorMessage(error), null, 'red');
                 }
               })
           })
@@ -1218,6 +1215,7 @@
             zipName : $('.panel-item.on').text().trim(),
           },
           success: (res)=>{
+            console.log(res);
             if (res.success === 'S') {
               let fileData = '';
               if (res.data) {
@@ -1267,6 +1265,7 @@
           },
           error : (error) => {
             console.log(error);
+            alertMessage('파일 다운로드', '파일 다운로드 중 오류가 발생했습니다.<br>' + getErrorMessage(error), null, 'red');
           }
 
           
@@ -1274,6 +1273,23 @@
       }
     }
 
+    function getErrorMessage(error) {
+      let errorText = "";
+      if (error.response && error.response.status && error.response.statusText && error.response.data  && error.response.data.error) {
+        // console.log(error.response);
+        console.log('=============================== Axios Error ===============================')
+        console.log(error.response);
+        console.log(error.response.data.error);
+        errorText = `status : ${error.response.status} - ${error.response.statusText}<br>message : ${error.response.data.error.message}`;
+      }
+      else {
+        console.log('================================ Error =====================================')
+        console.log(error);
+        errorText = JSON.stringify(error);
+      }
+      return errorText;
+    }
+
     function drawPath(path, siteId, name) {
       let imgSrc = '';
       let panelStr = '';
@@ -1343,7 +1359,18 @@
           $(this).css('background-color', '#f5f5f5');
           const items = transfer.items;
           _formData = new FormData($('<form enctype="multipart/form-data"></form>')[0]);
+          // console.log(items);
           const result = await getFilesDataTransferItems(items);
+          console.log(result);
+          //alertMessage('파일 업로드', error, null, 'red')
+          if (result && result.length) {
+            for (let obj of result) {
+              if (obj.success === 'F') {
+                return alertMessage('파일 업로드', obj.message, null, 'red');
+              }
+            }
+          }
+
           upload(_formData);
       });
     }
@@ -1432,7 +1459,7 @@
           },
           error: (error) => {
             console.log(error);
-            alertMessage(alertTitle, JSON.stringify(error), null, 'red');
+            alertMessage(alertTitle, alertTitle + ' 중 오류가 발생했습니다.<br>' + getErrorMessage(error), null, 'red');
           },
           
         });
@@ -1515,72 +1542,23 @@
         }
     }
     
-  //   function getFilesDataTransferItems(dataTransferItems) {
-  //     function traverseFileTreePromise(item, folder) {
-  //       return new Promise(resolve => {
-  //         let subfolder = [];
-  //         let files = [];
-  //         let fileObj = {};
-
-  //         if (item.isFile) {
-  //           item.file(file => {
-  //             let fileName = file.name;
-  //             // if (file.name.indexOf('.') > 0) {
-  //             //   fileName = file.name.substring(0, file.name.lastIndexOf('.'));
-  //             // }
-  //             let path = item.fullPath.substring(0, item.fullPath.lastIndexOf('/'));
-  //             if (!path) {
-  //               path = '';
-  //             }
-  //             _formData.append('file', file);
-  //             _formData.append(fileName + '_path', path);
-  //             resolve(fileObj);
-  //           });
-  //         } else if (item.isDirectory) {
-  //           let dirReader = item.createReader();
-  //           const path = item.fullPath.substring(0, item.fullPath.lastIndexOf('/'));
-  //           _formData.append('folder', JSON.stringify({name : item.name, path : path}));
-  //           dirReader.readEntries(entries => {
-  //             let entriesPromises = [];
-  //             fileObj = {
-  //               path : item.fullPath,
-  //               param : {
-  //                 name: item.name,
-  //                 folder: {},
-  //                 '@microsoft.graph.conflictBehavior': 'rename'
-  //               },
-  //               subfolder : subfolder,
-  //             };
-  //             folder.push(fileObj);
-                
-  //             for (let entr of entries) {
-                
-  //               entriesPromises.push(
-  //                 traverseFileTreePromise(entr, subfolder)
-  //               );
-  //             }
-  //             resolve(Promise.all(entriesPromises));
-  //           });
-  //         }
-  //       });
-  //     }
-
-  //     let files = [];
-  //     return new Promise((resolve, reject) => {
-  //       let entriesPromises = [];
-  //       for (let it of dataTransferItems)
-  //         entriesPromises.push(
-  //           traverseFileTreePromise(it.webkitGetAsEntry(), files)
-  //         );
-  //       Promise.all(entriesPromises).then(entries => {
-  //         resolve(files);
-  //       });
-  //     });
-  // }
-
-  function getFilesDataTransferItems(dataTransferItems) {
-      function traverseFileTreePromise(item, folder) {
-        return new Promise(resolve => {
+    async function getFilesDataTransferItems(dataTransferItems) {
+      const fileRows = $('.file-content > div');
+      const folderArr = [];
+      const fileArr   = [];
+      for (let ii = 0; ii < fileRows.length; ii++) {
+          const fileType = fileRows.eq(ii).children().eq(0).find('img').attr('alt');
+          const fileName = fileRows.eq(ii).children().find('.sp-name').text();
+          if (fileType === '폴더 이미지') {
+            folderArr.push(fileName);
+          }
+          else {
+            fileArr.push(fileName);
+          }  
+      }
+
+      async function traverseFileTreePromise(item, result) {
+        return await new Promise((resolve) => {
           let subfolder = [];
           let files = [];
           let fileObj = {};
@@ -1591,55 +1569,58 @@
               let path = item.fullPath.substring(0, item.fullPath.lastIndexOf('/'));
               if (!path) {
                 path = '';
+                let idx = fileArr.findIndex(obj => obj === fileName); 
+                if (idx >= 0) {
+                  result.push({success:'F', message:'업로드 경로에 이미 같은 이름의 파일이 있습니다.<br>파일을 업로드 하려면 기존 파일의 명칭을 변경해주세요.<br>파일명 : '+ fileName});
+                  resolve({success:'F', message:'업로드 경로에 이미 같은 이름의 파일이 있습니다.<br>파일을 업로드 하려면 기존 파일의 명칭을 변경해주세요.<br>파일명 : '+ fileName});
+                  // return alertMessage('파일 업로드','업로드 경로에 이미 같은 이름의 파일이 있습니다.<br>파일을 업로드 하려면 기존 파일의 명칭을 변경해주세요.<br>파일명 : '+ fileName);
+                }
               }
               _formData.append('file', file);
               _formData.append(fileName + '_path', path);
               _formData.append('file_path', path);
-              resolve(fileObj);
+              result.push({success: 'S', message:''});
+              resolve({success: 'S', message:''});
             });
           } 
           else if (item.isDirectory) {
             let dirReader = item.createReader();
             const path = item.fullPath.substring(0, item.fullPath.lastIndexOf('/'));
+            if (!path) {
+              let idx = folderArr.findIndex(obj => obj === item.name);
+              if (idx >= 0) {
+                result.push({success:'F', message:'업로드 경로에 이미 같은 이름의 폴더가 있습니다.<br>파일을 업로드 하려면 기존 폴더 명칭을 변경해주세요.<br>폴더명 : '+ item.name});
+                resolve({success:'F', message:'업로드 경로에 이미 같은 이름의 폴더가 있습니다.<br>폴더를 업로드 하려면 기존 폴더 명칭을 변경해주세요.<br>폴더명 : '+ item.name});
+              }
+            }
             _formData.append('folder', JSON.stringify({name : item.name, path : path}));
-            dirReader.readEntries(entries => {
+            dirReader.readEntries(async (entries) => {
               let entriesPromises = [];
-              fileObj = {
-                path : item.fullPath,
-                param : {
-                  name: item.name,
-                  folder: {},
-                  '@microsoft.graph.conflictBehavior': 'rename'
-                },
-                subfolder : subfolder,
-              };
-              folder.push(fileObj);
-                
               for (let entr of entries) {
-                
                 entriesPromises.push(
-                  traverseFileTreePromise(entr, subfolder)
+                  traverseFileTreePromise(entr, result)
                 );
               }
               resolve(Promise.all(entriesPromises));
             });
           }
-        });
+        })
       }
 
-      let files = [];
-      return new Promise((resolve, reject) => {
+      let result = [];
+      return await new Promise(async (resolve, reject) => {
         let entriesPromises = [];
         for (let it of dataTransferItems)
           entriesPromises.push(
-            traverseFileTreePromise(it.webkitGetAsEntry(), files)
+            traverseFileTreePromise(it.webkitGetAsEntry(), result)
           );
-        Promise.all(entriesPromises).then(entries => {
-          resolve(files);
+        await Promise.all(entriesPromises).then(entries => {
+          resolve(result);
         });
       });
   }
 
+
     function encryptFile(file, driveId) {
       const extArr = [ 
         'lnk', 'exe', 'com', 'cmd', 'bat', 'dll', 'ini', 
@@ -1683,6 +1664,7 @@
             },
             error: (error)=> {
               console.log(error);
+              alertMessage('API 호출', 'API 호출 중 오류가 발생했습니다.<br>' + getErrorMessage(error), null, 'red');
             }
         });
     }
@@ -1781,6 +1763,7 @@
           },
           error: (error)=> {
             console.log(error);
+            alertMessage('그룹 정보', '그룹 정보 호출 중 오류가 발생했습니다.<br>' + getErrorMessage(error), null, 'red');
           }
       })
     }
@@ -1848,8 +1831,158 @@
       }
     }
 
+    function drawFileContent(jsonData) {
+      const $fileContent = $('.file-content');
+      let str = '';
+      jsonData.forEach((obj, idx)=>{
+        dragAndDrop();
+
+        let modifyName = "";
+        if (obj.lastModifiedBy && obj.lastModifiedBy.user) {
+          modifyName = obj.lastModifiedBy.user.displayName;
+        }
+        const imageData = getFileImage(obj);
+        const images = imageData[0];
+        const imageName = imageData[1];
+        let amount = '0 Bytes';
+        if (obj.size) {
+          amount = getVolume(obj.size);
+        }
+        let modifyDate = obj.lastModifiedDateTime;
+        if (modifyDate) {
+          modifyDate = modifyDate.replace('T', ' ');
+          modifyDate = modifyDate.substring(5, 7)+ '월 '+ modifyDate.substring(8, 10)+ '일';
+        }
+
+        let method = `siteDriveChildrenItems('${obj.parentReference.siteId}','${obj.parentReference.path + '/' + obj.name}','${name}', null, event)`;
+        if (obj.file) {
+          method = `openWebUrl('${obj.webUrl}', '${obj.name}', event)`;
+        }
+        str += `
+          <div id="row_${idx}">
+            <div>
+              <input type="checkbox" name="row_${idx}" value="${obj.id}" onchange="checkState(event)" onclick="event.stopPropagation()">
+              <img src="${images}" width="32" height="32" alt="${imageName}">
+            </div>
+            <div class="file_name"><span class="sp-name" onclick="${method}">${obj.name}</span></div>
+            <div>${amount}</div>
+            <div>${modifyDate}</div>
+            <div>${modifyName}</div>
+            <div></div>
+          </div>`
+      });
+      $fileContent.html(str);
+      $('.file-content > div').on('click', function(e){
+            e.preventDefault();
+            const checkbox = $('input[name="'+$(this).attr('id') + '"]');
+            if (checkbox[0]) {
+              const isChecked = checkbox.prop("checked");
+              checkbox.prop('checked', !isChecked);
+              const method = !isChecked ? 'addClass' : 'removeClass';
+              $(this)[method]('on');
+            }
+          });
+
+          window.addEventListener('click', ()=>{
+              if ($('.toggle-box')[0]){
+                $('.toggle-box').remove();
+              }
+          })
+
+          $('.file-content > div').on('mousedown', function(e){
+            if ((e.button == 2) || (e.which == 3)) {
+              const checkbox = $('input[name="'+$(this).attr('id') + '"]');
+              if (!$(this).hasClass('on')) {
+                checkbox.prop('checked', true);
+                $(this).addClass('on');
+              }
+
+              if ($('.toggle-box')[0]) {
+                $('.toggle-box').remove();
+              }
+
+              const {clientX, clientY} = e;
+              const array = $('.file-content input[type="checkbox"]');
+              let checkCnt = 0;
+              let isChannel = false;
+              if (array && array.length > 0) {
+                for (let ii = 0; ii < array.length; ii++) {
+                  if (array.eq(ii).is(':checked')) {
+                      checkCnt++;
+                      const chanel = document.getElementById(array.eq(ii).val());
+                      if (chanel) {
+                        isChannel = true;
+                      }
+                  }
+                }
+              }
+
+              const teamId = $('section .panel .panel-item').eq(0).attr('id');
+              const teamList = document.querySelector('#my-team').nextElementSibling.nextElementSibling;
+              let bindId = '';
+              let isTeam = false;
+              const fileName = $('section .file-content div.on .sp-name').text();
+              
+              if (checkCnt === 1 && fileName) {
+                const frontId = 'com.microsoft.teamspace.tab.file.staticviewer.';
+                if (fileName.includes('.xlsx')) {
+                  bindId = frontId + 'excel';
+                }
+                else if (fileName.includes('.pdf')){
+                  bindId = frontId + 'pdf';
+                }
+                else if (fileName.includes('.pptx')) {
+                  bindId = frontId + 'powerpoint';
+                }
+                else if (fileName.includes('.docx')) {
+                  bindId = frontId + 'word';
+                }
+                else if (fileName.includes('.vsdx')) {
+                  bindId = frontId + 'visio';
+                }
+              }
+
+              if (teamList && $(teamList).find('#'+teamId+'_li').length > 0) {
+                isTeam = true;
+              }
+
+              let str = '';
+              if (bindId) {
+                str += `<div>편집</div>`;
+              }
+              const selectImage = $('section .file-content div.on').find('img');
+              if (
+                  checkCnt === 1     && 
+                  selectImage.length && 
+                  isTeam === true    &&
+                  (selectImage.attr('src') !== '/static/images/folder.png') &&
+                  bindId
+                ) {
+                str += `<div onclick="addTabs('${bindId}')">탭으로 설정</div>`;
+              }
+              str += `<div onclick="download()">다운로드</div>
+                      <div onclick="deleteItem()">삭제</div>`;
+
+              if (!isChannel) {
+                str +=`<div onclick="moveItem('이동')">이동</div>`;
+              }
+
+              str += `<div onclick="moveItem('복사')">복사</div>`;
+              
+              if (checkCnt === 1) {
+                str += `<div onclick="nameChange()">이름 바꾸기</div>`;
+              }
+              const toggleBox = $(`<div class="toggle-box" style="position:absolute; top:${clientY}; left: ${clientX}">
+                  ${str}
+                </div>`);
+                $('body').append(toggleBox);
+            }
+          });
+    }
 
     function sorting(type) {
+      if ($('.file-content').children().length === 0) return;
+      
       const $sortingColumn = $('.head-'+type);
       const isSelected = $sortingColumn.hasClass('on');
       if ($('.file-title > div.on')[0]) {
@@ -1866,14 +1999,23 @@
           first = -1;
           end = 1; 
         }
-        
-
-        _selectedData.value.sort(function (a, b){
-          return a[type] > b[type] ? first : a[type] === b[type] ? 0 : end;
+        console.log(_selectedData);
+        const sortData = [..._selectedData.value];
+        sortData.sort(function (a, b){
+          if (type === 'lastModifiedBy') {
+            const aVal = a.lastModifiedBy.user.displayName;
+            const bVal = b.lastModifiedBy.user.displayName;
+            return aVal > bVal ? first : aVal === bVal ? 0 : end;  
+          }
+          else {
+            return a[type] > b[type] ? first : a[type] === b[type] ? 0 : end;
+          }
         });
-        console.log(_selectedData.value);
+
+        drawFileContent(sortData);
       }
   }
+  
   $('.tree.group input[type="checkbox"]').on('change', function(event){
     console.log($(this));
   })
@@ -1945,8 +2087,8 @@
         alertMessage(name, res.message, null, color);
       },
       error: (error) => {
-        console.log('==============error=============\n');
         console.log(error);
+        alertMessage('새로 만들기', '새로 만들기 작업 중 오류가 발생했습니다.<br>' + getErrorMessage(error), null, 'red');
       }
       
     })
@@ -2093,9 +2235,6 @@
       ext = name.substring(name.lastIndexOf("."));
       width = 'calc(100% - 35px)';
     }
-    // callApi('get', "/sites/"+ siteId + "/drive/items/" + itemId, (jsonData)=>{
-    //   console.log(jsonData);
-    // })
   
     const modalContainer = $(
       `<div class="modal name" style="display: flex;">
@@ -2145,7 +2284,7 @@
           alertMessage('이름 변경',res.message);
       },
       error : (error) => {
-          alertMessage('이름 변경','오류가 발생하였습니다.<br>'+ error);
+          alertMessage('이름 변경','이름 변경 중 오류가 발생하였습니다.<br>' + getErrorMessage(error));
       }
     })
   }