• דף הבית
    • אינדקס קישורים
    • פוסטים אחרונים
    • משתמשים
    • חיפוש בהגדרות המתקדמות
    • חיפוש גוגל בפורום
    • ניהול המערכת
    • ניהול המערכת - שרת private
    • הרשמה
    • התחברות

    העלאת תקיות שלימות בצורה מסודרת להפליא בלי להתאמץ😏🎮🕹🥱

    מתוזמן נעוץ נעול הועבר בקשות לפיתוח
    21 פוסטים 5 כותבים 273 צפיות 4 עוקבים
    טוען פוסטים נוספים
    • מהישן לחדש
    • מהחדש לישן
    • הכי הרבה הצבעות
    תגובה
    • תגובה כנושא
    התחברו כדי לפרסם תגובה
    נושא זה נמחק. רק משתמשים עם הרשאות מתאימות יוכלו לצפות בו.
    • א מחובר
      אA
      נערך לאחרונה על ידי אA

      הקוד המעודכן:

      <!DOCTYPE html>
      <html lang="he" dir="rtl">
      <head>
          <meta charset="UTF-8">
          <title>מעלה תקיות וקבצים למערכת - עץ שלוחות</title>
          <style>
              :root {
                  --primary: #3498db; --success: #2ecc71; --danger: #e74c3c; --bg: #f4f7f6; --dark: #2c3e50;
              }
              body { font-family: 'Segoe UI', Arial, sans-serif; margin: 0; background-color: var(--bg); color: var(--dark); text-align: right; }
              .wrapper { max-width: 900px; margin: 40px auto; padding: 0 20px; position: relative; }
              .reset-btn { position: absolute; top: -10px; left: 20px; background: var(--danger); color: white; border: none; padding: 8px 15px; border-radius: 5px; cursor: pointer; font-size: 14px; font-weight: bold; transition: all 0.3s; }
              .card { background: white; padding: 30px; border-radius: 15px; box-shadow: 0 10px 25px rgba(0,0,0,0.05); margin-bottom: 25px; border: 1px solid #eee; }
              h2 { margin-top: 0; color: var(--dark); border-bottom: 3px solid var(--primary); display: inline-block; padding-bottom: 10px; }
              .grid { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; margin-top: 20px; }
              .input-group { display: flex; flex-direction: column; gap: 8px; }
              label { font-weight: bold; font-size: 14px; }
              input { padding: 12px; border: 2px solid #eee; border-radius: 8px; font-size: 16px; }
              .full-width { grid-column: 1 / -1; }
              .btn-main { background: var(--primary); color: white; border: none; padding: 15px; border-radius: 8px; cursor: pointer; font-size: 18px; font-weight: bold; width: 100%; transition: all 0.3s; }
              .btn-main:hover { background: #2980b9; }
              .btn-main:disabled { background: #bdc3c7; cursor: not-allowed; }
              .progress-wrapper { margin-top: 25px; display: none; padding: 15px; background: #fafafa; border-radius: 10px; border: 1px solid #eee; }
              .progress-container { width: 100%; background: #e0e0e0; height: 35px; border-radius: 20px; overflow: hidden; position: relative; border: 1px solid #ccc; }
              .progress-bar { 
                  height: 100%; width: 0%; 
                  background: linear-gradient(45deg, #2ecc71 25%, #27ae60 25%, #27ae60 50%, #2ecc71 50%, #2ecc71 75%, #27ae60 75%, #27ae60);
                  background-size: 40px 40px; animation: move-stripes 2s linear infinite; transition: width 0.4s;
              }
              @keyframes move-stripes { from { background-position: 40px 0; } to { background-position: 0 0; } }
              .progress-text { position: absolute; width: 100%; text-align: center; top: 0; line-height: 35px; color: #fff; font-weight: 900; text-shadow: 1px 1px 2px rgba(0,0,0,0.5); }
              .log-box { background: #1e1e1e; color: #d4d4d4; padding: 20px; border-radius: 10px; font-family: 'Consolas', monospace; height: 300px; overflow-y: auto; font-size: 13px; line-height: 1.6; border: 4px solid #333; }
              .log-info { color: #5dade2; }
              .log-success { color: #58d68d; font-weight: bold; }
              .log-error { color: #ec7063; }
              .log-warn { color: #f4d03f; }
          </style>
      </head>
      <body>
       
      <div class="wrapper">
          <button class="reset-btn" onclick="location.reload()">✕ איפוס תהליך</button>
          <div class="card">
              <h2>מעלה תקיות וקבצים למערכת - עץ שלוחות</h2>
              <div class="grid">
                  <div class="input-group">
                      <label>טוקן:</label>
                      <input type="text" id="token">
                  </div>
                  <div class="input-group">
                      <label>שלוחת יעד:</label>
                      <input type="text" id="targetPath">
                  </div>
                  <div class="input-group" style="flex-direction: row; align-items: center; gap: 5px;">
                      <input type="checkbox" id="autoFileNum"> <label for="autoFileNum">מספור קבצים (אוטומטי)</label>
                  </div>
                  <div class="input-group" style="flex-direction: row; align-items: center; gap: 5px;">
                      <input type="checkbox" id="autoFolderNum"> <label for="autoFolderNum">מספור שלוחות (אוטומטי)</label>
                  </div>
                  <div class="input-group full-width">
                      <label>בחירת תיקייה:</label>
                      <input type="file" id="folderInput" webkitdirectory>
                  </div>
                  <button id="startBtn" class="btn-main" onclick="processUpload()">התחל העלאה</button>
              </div>
              <div class="progress-wrapper" id="progBox">
                  <div class="progress-container">
                      <div class="progress-bar" id="progBar"></div>
                      <div class="progress-text" id="progText">0%</div>
                  </div>
              </div>
          </div>
          <div class="card">
              <div class="log-box" id="logBox">ממתין...</div>
          </div>
      </div>
       
      <script>
          const CHUNK_SIZE = 4 * 1024 * 1024;
          const MAX_SINGLE_FILE = 50 * 1024 * 1024;
          const sleep = ms => new Promise(res => setTimeout(res, ms));
          const generateUUID = () => 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
              let r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
              return v.toString(16);
          });
       
          function addLog(msg, type = "info") {
              const logBox = document.getElementById('logBox');
              logBox.innerHTML += `<div class="log-${type}">> ${msg}</div>`;
              logBox.scrollTop = logBox.scrollHeight;
          }
       
          async function processUpload() {
              const token = document.getElementById('token').value.trim();
              const targetPath = document.getElementById('targetPath').value.trim().replace(/\/$/, "");
              const fileList = document.getElementById('folderInput').files;
              const autoFileNum = document.getElementById('autoFileNum').checked;
              const autoFolderNum = document.getElementById('autoFolderNum').checked;
              
              if (!token || !fileList.length || !targetPath) { alert("מלא פרטים"); return; }
              document.getElementById('startBtn').disabled = true;
              document.getElementById('progBox').style.display = 'block';
       
              const folderStructure = {};
              for (let file of fileList) {
                  const parts = file.webkitRelativePath.split('/'); parts.shift();
                  const fileName = parts.pop(); const relPath = parts.join('/');
                  if (!folderStructure[relPath]) folderStructure[relPath] = [];
                  folderStructure[relPath].push({ name: fileName, file: file });
              }
              if (!folderStructure[""]) folderStructure[""] = [];
       
              const sortedPaths = Object.keys(folderStructure).sort((a,b) => (a===""?-1:b===""?1:a.split('/').length - b.split('/').length));
       
              // לוגיקת מספור שלוחות
              const folderRenameMap = {};
              if (autoFolderNum) {
                  sortedPaths.forEach(path => {
                      if (path === "") return;
                      const parts = path.split('/');
                      const mappedParts = [];
                      parts.forEach((part, index) => {
                          const parentPath = parts.slice(0, index).join('/');
                          const siblings = sortedPaths.filter(p => p !== "" && p.split('/').length === index + 1 && p.split('/').slice(0, index).join('/') === parentPath).sort();
                          mappedParts.push(siblings.indexOf(parts.slice(0, index + 1).join('/')) + 1);
                      });
                      folderRenameMap[path] = mappedParts.join('/');
                  });
              }
       
              for (let i = 0; i < sortedPaths.length; i++) {
                  const relPath = sortedPaths[i];
                  const finalSubPath = (autoFolderNum && relPath !== "") ? folderRenameMap[relPath] : relPath;
                  const currentIvrPath = finalSubPath ? `${targetPath}/${finalSubPath}` : targetPath;
                  const files = folderStructure[relPath];
       
                  // ext.ini
                  const extFileObj = files.find(f => f.name.toLowerCase().split('.')[0] === 'ext');
                  let extContent = extFileObj ? await extFileObj.file.text() : (relPath === "" ? "type=menu" : "type=playfile");
                  await uploadFileNormal(token, `${currentIvrPath}/ext.ini`, new Blob([extContent], {type: 'text/plain'}));
                  addLog(`שלוחה ${currentIvrPath} הוגדרה`, "success");
       
                  files.sort((a, b) => a.name.localeCompare(b.name, undefined, {numeric: true}));
                  let audioCount = 0;
       
                  for (let fObj of files) {
                      if (fObj.name.toLowerCase().split('.')[0] === 'ext') continue;
                      let destName = fObj.name; let blob = fObj.file;
       
                      if (/\.(wav|mp3|ogg|wma)$/i.test(fObj.name)) {
                          destName = (autoFileNum ? audioCount.toString().padStart(3, '0') : fObj.name.replace(/\.[^/.]+$/, "")) + ".wav";
                          audioCount++;
                      } else if (fObj.name.toLowerCase().includes('.tts')) {
                          destName = fObj.name.split('.')[0] + ".tts";
                          blob = new Blob([await fObj.file.text()], {type: 'text/plain'});
                      }
       
                      if (blob.size > MAX_SINGLE_FILE) {
                          await uploadFileChunked(token, currentIvrPath, destName, blob);
                      } else {
                          await uploadFileNormal(token, `${currentIvrPath}/${destName}`, blob);
                      }
                      addLog(`הועלה: ${destName}`, "info");
                  }
       
                  const pct = Math.round(((i + 1) / sortedPaths.length) * 100);
                  document.getElementById('progBar').style.width = pct + '%';
                  document.getElementById('progText').innerText = pct + '%';
              }
              addLog("העלאה הסתיימה בהצלחה!", "success");
              document.getElementById('startBtn').disabled = false;
          }
       
          async function uploadFileNormal(token, fullPath, blob) {
              const fd = new FormData();
              fd.append('token', token); fd.append('path', `ivr2:${fullPath}`);
              fd.append('qqfile', blob, fullPath.split('/').pop());
              const res = await fetch(`https://www.call2all.co.il/ym/api/UploadFile`, { method: 'POST', body: fd });
              return await res.json();
          }
       
          async function uploadFileChunked(token, folderPath, fileName, fileBlob) {
              const uuid = generateUUID();
              const totalParts = Math.ceil(fileBlob.size / CHUNK_SIZE);
              addLog(`מפצל קובץ גדול: ${fileName}`, "warn");
              for (let index = 0; index < totalParts; index++) {
                  const start = index * CHUNK_SIZE; const end = Math.min(start + CHUNK_SIZE, fileBlob.size);
                  const chunk = fileBlob.slice(start, end);
                  const fd = new FormData();
                  fd.append('qquuid', uuid); fd.append('qqpartindex', index);
                  fd.append('qqpartbyteoffset', start); fd.append('qqchunksize', chunk.size);
                  fd.append('qqtotalparts', totalParts); fd.append('qqtotalfilesize', fileBlob.size);
                  fd.append('qqfilename', fileName); fd.append('uploader', 'yemot-admin');
                  fd.append('qqfile', chunk, fileName);
                  await fetch(`https://www.call2all.co.il/ym/api/UploadFile`, { method: 'POST', body: fd });
              }
              const finalUrl = `https://www.call2all.co.il/ym/api/UploadFile?done&token=${token}&path=ivr2:${folderPath}/${fileName}&qquuid=${uuid}&qqfilename=${fileName}&qqtotalfilesize=${fileBlob.size}&qqtotalparts=${totalParts}`;
              const res = await fetch(finalUrl, { method: 'POST' });
              return await res.json();
          }
      </script>
      </body>
      </html>
      
      תגובה 1 תגובה אחרונה תגובה ציטוט 0
      • א מחובר
        אA
        נערך לאחרונה על ידי

        הוספתי תמיכה בקבצים גדולים.
        אשמח שתבדקו

        L ע 2 תגובות תגובה אחרונה תגובה ציטוט 0
        • L מנותק
          lavitoren הטי"ל @אA
          נערך לאחרונה על ידי lavitoren הטי"ל

          @אA החדש פשוט מ-ד-ה-י-ם!!!!! (כמעט כמוך😉 ) ועובד מצוין (למעט מה שנכתב בהערה למטה)
          ושוב אין מילים להודות לך על העבודה המאומצת המושלמת והמדוייקת

          סיכום הדברים:

          א. גם הופסת את אפשרות המספור - למעוניין!
          גם לקבצים וגם לשלוחות ולפי בחירה שזה גאונות לא מעלמא הדין!!!
          וזה עובד מטורף וזה פותח כמובן את השלוחות בדיוק וממספר (בחרתי שימספר כמובן) מהגדול לקטן אצלי בבדיקה קודם את 2 ואז את 1
          [בשביל להפוך את זה למושלם אולי כדאי לעשות בחירה האם רוצה מהגדול לקטן או לא (אני לא צריך וגם זה זניח גם כיוון שאפשר פשוט לשנות שם שלוחה אבל סתם ברעיון)]
          וזה פשוט עובד ועובד טוב!🎧 כל כך קל כמו לשחק אם איזה שלט 🕹 או לטוס לחלל 🗼
          ב. עשית את העלאת הקבצים הגדולה חכם כל כך שזה מתפצל אם זה גדול מדי ובדקתי
          תקלה.PNG
          מצב.PNG
          וזה לא כל כך עבד

          (כדי להזכיר לנו שאנחנו לא מלאכים אבל לא רחוקים משם אי"ה אם מאמץ מיוחד בעבודתו יתברך)

          אבל בסייעתא דשמיא אקוה שהחכמה שה' יתברך חנן את @אA יעזרהו להתגבר אף על זה

          נ. ב. בקו מראה את הקבצים מיד כשכתוב הועלה אז אם לא רואים סימן שזה תקלה!

          אם צריך לתאר בסימנים את מה שקורה פה צריך לפחות את כל אלו!!
          🔊📣📢🔉🔈🎙🎤🎚🎹📻📠📟💻🔌🖥🖱⌨🖨📺📷📼📽🎬🎥📸📹
          אשריך ושוב תודה ענקית מקרב לבי ואני מאמין שמקרב לב רבים וטובים בהווה ובעתיד

          הערות: עכשיו נשאר ה"תיקון האחרון והסופי שזה - הקבצים מועלים באיכות של המחשב ולא באיכות טלפון ולכן אפשר לפתוח במחשב אבל בטלפון
          שומעים "שגיאה" ואני מבין שמן הסתם זה קשור להעלאת הקבצים הגדולים שצריך להפוך אותם ל MP3 אבל כנראה גם זה לא הצליח!
          אם יש אפשרות אז לעשות שלפני שמעלה לקו בתוך הקו שיהפך לאיכות טלפון (או אם יש אפשרות האיכות הכי משופרת שניתן להפיק מהטלפון שאפשר לשמוע מהטלפון)

          א תגובה 1 תגובה אחרונה תגובה ציטוט 0
          • ע מנותק
            עידו @אA
            נערך לאחרונה על ידי

            @אA מנסיון, הבינה מלאכותית מאוד מסתבכת עם העלאת קבצים גדולים, עוד לא הצלחתיליצר איתם אף קוד של העלאת קבצים גדולים.

            L תגובה 1 תגובה אחרונה תגובה ציטוט 1
            • א מחובר
              אA @lavitoren הטי"ל
              נערך לאחרונה על ידי אA

              @lavitoren-הטי-ל
              קודם תודה על כל המחמאות (זה נותן הרבה חשק להמשיך ולפתח).
              לפי מה שנראה במסך הלוג, הקובץ כן נקלט רק שלאחר שחולק הוא לא עלה באופן תקין למערכת.
              אני אנסה לתקן את זה ואם הבינה תסתבך כמו שכתב @עידו אני הבהיר לו מה לעשות ונקווה שיעבוד.

              ע L 2 תגובות תגובה אחרונה תגובה ציטוט 2
              • ע מנותק
                עידו @אA
                נערך לאחרונה על ידי

                @אA gpt מסתבך קבוע, לא משנה כמה ניסיתי להבהיר לו... אבל אולי אתה תוכל הלבהיר יותר טוב.

                תגובה 1 תגובה אחרונה תגובה ציטוט 0
                • L מנותק
                  lavitoren הטי"ל @עידו
                  נערך לאחרונה על ידי

                  @עידו נכון ניסיתי והוא לא הצליח לפני ש@אA הביא את החדש
                  ולדעתי הוא בנה ללא בינה כי אני ניסיתי 5 פעמים והבינה הציעה לי לעשות מרווח זמן בהתחלה של 0.6 שניות בין קובץ לקובץ וגם את מה שהוא עשה להשאיר ברמת MP3 גבוהה
                  ותמיד שכחה משהו אחר!

                  א תגובה 1 תגובה אחרונה תגובה ציטוט 0
                  • L מנותק
                    lavitoren הטי"ל @אA
                    נערך לאחרונה על ידי lavitoren הטי"ל

                    @אA תודה ע-נ-ק-י-ת!!!!!!!
                    ו......ממתין בכליון עינים

                    תגובה 1 תגובה אחרונה תגובה ציטוט 1
                    • א מחובר
                      אA @lavitoren הטי"ל
                      נערך לאחרונה על ידי אA

                      @lavitoren-הטי-ל @עידו
                      אני לא מסתיר...
                      הכל אני עושה עם הבינה, רק שאני לא נותן לה סתם ליצור לי אלא נותן לה הדרכה צפופה מאוד מה לעשות, גם בעיצוב וגם בקודים ובצורת ההרצה שלהם.

                      L תגובה 1 תגובה אחרונה תגובה ציטוט 2
                      • L מנותק
                        lavitoren הטי"ל @אA
                        נערך לאחרונה על ידי

                        @אA וואי וואי אז זה נראה לי יותר קשה פי כמה וכמה
                        למה היא תמיד עושה בעיות אז עוד יותר תודה ועוד יותר תודה ועוד יותר תודה ועוד יותר תודה.....😉

                        תגובה 1 תגובה אחרונה תגובה ציטוט 1
                        • פוסט ראשון
                          פוסט אחרון