בחירת קבצים ואינטראקציה איתם במכשיר המקומי של המשתמש היא אחת של האינטרנט. הוא מאפשר למשתמשים לבחור קבצים להעלות אותם לשרת. לדוגמה, כשמשתפים תמונות או שולחים נתוני מס מסמכים. הוא גם מאפשר לאתרים לקרוא ולשנות אותם בלי כדי להעביר את הנתונים ברשת. בדף הזה מוסבר איך להשתמש JavaScript לאינטראקציה עם קבצים.
ה-File System Access API המודרני
File System Access API מאפשר לקרוא קבצים ולכתוב בהם במערכת המקומית של המשתמש. האפשרות הזו זמינה ברוב המקרים שמבוססים על Chromium בדפדפנים כמו Chrome ו-Edge. מידע נוסף זמין במאמר בנושא ממשק File System Access API
מאחר ש-File System Access API לא תואם לכל הדפדפנים, אנחנו מומלץ להשתמש ב-browser-fs-access, ספרייה משנית שמשתמשת ב-API החדש בכל מקום שבו הוא זמין בחזרה לגישות הקודמות, מתי שכבר לא.
עבודה עם קבצים, בדרך הקלאסית
במדריך הזה מוסבר איך לקיים אינטראקציה עם קבצים באמצעות שיטות JavaScript מדור קודם.
בחירת קבצים
יש שתי דרכים עיקריות לבחור קבצים: אלמנט הקלט ב-HTML, ושימוש ברכיב אזור גרירה ושחרור.
רכיב קלט HTML
הדרך הקלה ביותר למשתמשים לבחור קבצים היא
<input type="file">
שנתמך בכל דפדפן ראשי. כשמשתמש לוחץ עליו, הוא מאפשר
ולבחור קובץ אחד, או כמה קבצים, אם
multiple
באמצעות בחירת הקבצים המובנית של מערכת ההפעלה שלהם
ממשק משתמש. כשהמשתמש מסיים לבחור קובץ או קבצים, change
של הרכיב
הפעלות של אירועים. אפשר לגשת לרשימת הקבצים מ-event.target.files
,
הוא אובייקט FileList
.
כל פריט ב-FileList
הוא אובייקט File
.
<!-- The `multiple` attribute lets users select multiple files. -->
<input type="file" id="file-selector" multiple>
<script>
const fileSelector = document.getElementById('file-selector');
fileSelector.addEventListener('change', (event) => {
const fileList = event.target.files;
console.log(fileList);
});
</script>
הדוגמה הבאה מאפשרת למשתמש לבחור כמה קבצים לפי מערכת ההפעלה שלהם את ממשק המשתמש המובנה לבחירת קבצים, ולאחר מכן רושם כל קובץ שנבחר במסוף.
הגבלת סוגי הקבצים שהמשתמשים יכולים לבחור
במקרים מסוימים, ייתכן שתרצו להגביל את סוגי הקבצים שהמשתמשים יכולים לבחור. עבור
לדוגמה, אפליקציה לעריכת תמונות צריכה לקבל רק תמונות ולא קובצי טקסט. כדי להגדיר
הגבלות על סוגי קבצים, הוספת
accept
מאפיין לרכיב הקלט כדי לציין אילו סוגי קבצים יתקבלו:
<input type="file" id="file-selector" accept=".jpg, .jpeg, .png">
גרירה ושחרור בהתאמה אישית
בדפדפנים מסוימים, גם הרכיב <input type="file">
מהווה ירידה ביעד,
שמאפשר למשתמשים לגרור קבצים ולשחרר אותם באפליקציה. אבל היעד הזה ירד
הוא קטן וקשה להשתמש בו. במקום זאת, אחרי שתספקו תכונות ליבה באמצעות
רכיב <input type="file">
, אפשר לספק רכיב גרירה ושחרור גדול ומותאם אישית
פלטפורמה.
בחירת אזור ירידה
פלטפורמת ההשקה תלויה בעיצוב האפליקציה. ייתכן שתרצו רק חלק מהחלון בתור משטח, אבל אתם יכולים להשתמש בכל החלון.
האפליקציה לדחיסת תמונות Squoosh מאפשרת למשתמש לגרור תמונה למקום כלשהו
ולוחצים על בחירת תמונה כדי להפעיל את <input type="file">
לרכיב מסוים. לא משנה מה יהיה אזור השחרור שלך, חשוב לוודא שהוא ברור למשתמש
כדי לגרור קבצים למשטח הזה.
הגדרת אזור הירידה
כדי להפעיל רכיב כאזור גרירה ושחרור, צריך ליצור פונקציות listener עבור
שני אירועים: dragover
ו-drop
.
האירוע dragover
מעדכן את ממשק המשתמש של הדפדפן כדי לציין באופן חזותי ש
פעולת הגרירה והשחרור יוצרת עותק של הקובץ. האירוע drop
מופעל
אחרי שהמשתמש משחרר את הקבצים על המסך. בדומה לרכיב הקלט, ניתן
יכול לגשת לרשימת הקבצים מ-event.dataTransfer.files
,
אובייקט FileList
. כל אחד
ב-FileList
הוא אובייקט File
.
const dropArea = document.getElementById('drop-area');
dropArea.addEventListener('dragover', (event) => {
event.stopPropagation();
event.preventDefault();
// Style the drag-and-drop as a "copy file" operation.
event.dataTransfer.dropEffect = 'copy';
});
dropArea.addEventListener('drop', (event) => {
event.stopPropagation();
event.preventDefault();
const fileList = event.dataTransfer.files;
console.log(fileList);
});
event.stopPropagation()
ו-event.preventDefault()
לעצור את התנהגות ברירת המחדל של הדפדפן ולאפשר לקוד לפעול. בלעדיהם,
אחרת, הדפדפן היה מנווט אל מחוץ לדף ופותח את הקבצים
המשתמש נפל לחלון הדפדפן.
אפשר להיעזר בהדגמה של גרירה ושחרור בהתאמה אישית כדי לראות הדגמה בזמן אמת.
מה לגבי ספריות?
לצערנו, אין דרך טובה לגשת לספרייה באמצעות JavaScript.
webkitdirectory
ברכיב <input type="file">
מאפשר למשתמש לבחור ספרייה
או ספריות. הוא נתמך ברוב הדפדפנים המובילים
חוץ מ-Firefox ל-Android ו-Safari ב-iOS.
אם מופעלת גרירה ושחרור, משתמש עשוי לנסות לגרור ספרייה לתוך
טווח ירידה. כשהאירוע של שחרור מופעל, הוא כולל אובייקט File
עבור
אבל לא מספקת גישה לאף אחד מהקבצים בספרייה.
לקרוא מטא-נתונים של קבצים
האובייקט File
מכיל מטא-נתונים של הקובץ. רוב הדפדפנים
מספקים את שם הקובץ, את גודל הקובץ ואת סוג ה-MIME, אם כי בהתאם
בפלטפורמה, דפדפנים שונים עשויים לספק
מידע.
function getMetadataForFileList(fileList) {
for (const file of fileList) {
// Not supported in Safari for iOS.
const name = file.name ? file.name : 'NOT SUPPORTED';
// Not supported in Firefox for Android or Opera for Android.
const type = file.type ? file.type : 'NOT SUPPORTED';
// Unknown cross-browser support.
const size = file.size ? file.size : 'NOT SUPPORTED';
console.log({file, name, type, size});
}
}
אפשר לראות את זה בפעולה בinput-type-file
.
קריאת התוכן של קובץ
שימוש ב-FileReader
כדי
קריאת התוכן של אובייקט File
בזיכרון. אפשר לבקש מFileReader
:
לקרוא קובץ כמאגר אחסון זמני של מערך,
כתובת URL של נתונים,
או טקסט:
function readImage(file) {
// Check if the file is an image.
if (file.type && !file.type.startsWith('image/')) {
console.log('File is not an image.', file.type, file);
return;
}
const reader = new FileReader();
reader.addEventListener('load', (event) => {
img.src = event.target.result;
});
reader.readAsDataURL(file);
}
בדוגמה הזו קוראים File
שסופק על ידי המשתמש, ואז ממירים אותו לנתונים
כתובת URL, ומשתמשת בכתובת ה-URL של הנתונים הזו כדי להציג את התמונה ברכיב img
.
כדי לוודא שהמשתמש בחר קובץ תמונה, אפשר לעיין
הדגמה של read-image-file
.
מעקב אחר ההתקדמות של קריאת קובץ
כשקוראים קבצים גדולים, כדאי לספק חוויית משתמש כדי ליידע את המשתמש
טווח ההתקדמות של הקריאה. לשם כך, משתמשים
progress
האירוע סופק על ידי FileReader
. לאירוע progress
יש שני מאפיינים:
loaded
(הסכום שנקרא) ו-total
(הסכום לקריאה).
function readFile(file) {
const reader = new FileReader();
reader.addEventListener('load', (event) => {
const result = event.target.result;
// Do something with result
});
reader.addEventListener('progress', (event) => {
if (event.loaded && event.total) {
const percent = (event.loaded / event.total) * 100;
console.log(`Progress: ${Math.round(percent)}`);
}
});
reader.readAsDataURL(file);
}
התמונה הראשית (Hero) של וינסנט בוטה מתוך Unbounce