
express ואת express-fileupload. השנייה נדרשת כי Express לא יכול לשמור קבצים שמגיעים מהמשתמש. בקוד טוענים אותן עם require, וגם את fs לשמירה בדיסק.index.html עם express.static מהתיקייה הראשית (__dirname), ומעלים אותו על פורט 3000 עם הודעת listening.server.use עם הפונקציה fileUpload. היא לוקחת קובץ שהגיע בבקשה ומציבה אותו ב-request.files, שבלעדיה לא קיים.action שווה לראוט, method הוא POST, ובנוסף חובה enctype עם הערך multipart/form-data, אחרת הטופס בכלל לא שולח קבצים. ה-input הוא מסוג file, וצריך לתת לו name. המרצה בוחר mySingleImage.request.files, והוא מחזיר אובייקט שמתאר את הקובץ כולו. לאובייקט יש פונקציה mv (קיצור של move), שמקבלת את היעד, כאן תיקיית uploads. בסוף מחזירים ללקוח תשובה, למשל done, אחרת הוא לא יקבל כלום.fs.existsSync ואם התיקייה לא קיימת יוצרים אותה עם fs.mkdirSync. משתמשים בגרסה הסינכרונית כי זה קורה רק בעליית השרת, ואין צורך להסתבך עם async ו-await.uuid וטוענים אותה. את הסיומת המקורית שולפים עם substr ו-lastIndexOf של נקודה, כך שהיא כוללת את הנקודה. שומרים את הקובץ בשם שנוצר ב-uuid גרסה 4, ואחריו הסיומת. התוצאה היא מחרוזת ייחודית באורך 36 תווים. הסיומת נשמרת כי יכולה להיות כל סיומת, והתוכנית תומכת בכל סוג קובץ ולא רק בתמונות.accept ב-input מגבילה את הבחירה, למשל לסוג jpeg בלבד, או ל-image/* לכל התמונות.npm i express express-fileupload והתקנה נפרדת של uuidreq.files, file.mv, fs.existsSync, fs.mkdirSyncenctype עם הערך multipart/form-data וגם name בשדה הקובץaccept עם הערך image/*node appenctype של multipart/form-data הטופס לא שולח קבצים.name ב-input השרת לא מוצא את הקובץ.uploads ההעלאה קורסת, אפילו שהלקוח קיבל done.הטקסט המלא של הדקות הראשונות בהרצאה «העלאת תמונה בודדת upload לאתר ב-NodeJS» בקורס הווידאו של PracticU – כתוביות בעברית עם זמן התחלה לכל פסקה. כך תוכלו לקרוא ולחפש את הנושאים לפני שמתחילים ללמוד.
הדבר הבא שאנחנו רוצים לעשות זה לאפשר למשתמש להעלות לאתר נניח תמונה. כמובן שהוא יוכל להעלות כל קובץ שהוא ירצה, לא רק תמונות, אבל אנחנו ניתן את הדוגמה הזאת על ידי העלאת תמונות.
אז דבר ראשון יש לנו פה פרויקט חדש לגמרי בכדי לא לערב את מה שעשינו מקודם עם העלאת תמונה ומה שאנחנו רוצים זה קודם כל התקנה של אקספרס ולאקספרס אין את היכולת לשמור קבצים מהיוזר כי ראינו בעבר שאקספרס מכילה רק את היכולת להיות מעין רסטפול סרוויס או להנגיש דברים בכדי לאפשר לשמור קבצים שמגיעים מהלקוח אנחנו צריכים להתקין עוד התקנה אחת
שנקראת אקספרס מקף פייל אפלוד אז כמובן שאנחנו יכולים בהתקנה אחת להתקין מספר התקנות הנה אקספרס התקנה אחת הנה express file upload התקנה שנייה בואו נתקין את זה ונתחיל לעלות למעלה בינתיים עד שהוא מתקין ולבנות לעצמנו פה את express require express ויש לנו פה כמובן גם את file upload require נלך ל express file upload כן קיצרתי לו פה את השם קראתי לו רק
פייל אפלוד. מה אנחנו בעצם רוצים לעשות עם התמונות שהיוזר מעלה לאתר שלנו, לשרת שלנו? אנחנו רוצים לשמור אותם בדיסק, אז בואו נייצר לעצמנו את פייל סיסטם בשביל לאפשר את השמירה.
require fs, ואנחנו רוצים להתחיל להעלות את השרת לאוויר. const server express, אנחנו רוצים להנגיש את דף האינדקס html, server use express static ובואו ניתן לו את הדף כך שהוא יישב לצורך הפשטות בתיקייה הראשית.
נתנו פה דיר ניים, נעלה את האתר על ידי server listen ואנחנו מוצאים על פורט 3000 כמו תמיד. ברגע שעלית תציג לנו listening on http://localhost 3000. אז קודם כל יש לנו כרגע את התשתית עצמה שהיא מכילה רק את ההתקנות הדרושות והעלאת המידע לאוויר, ומה שאנחנו רוצים עכשיו זה להתחיל להתעסק
עם ההעלאה עצמה. אז מה שקורה זה שאנחנו צריכים לתת הוראה לאקספרס להבין שיכול להיות שיש קבצים שמגיעים מהלקוח, זה לא משהו שהוא מגיע כדיפולט.
אקספרס לא מתעסקת עם קבצים אבל זאת המהות של התוכנית, אנחנו רוצים שהיוזר יאפשר לבחור איזשהו קובץ מהמחשב שלו, מהקליינט, ולשלוח אותו לסרבר.
אז אנחנו אומרים ל-express על ידי server.use ואנחנו קוראים ל-file.upload כפונקציה, file.upload זה בעצם פונקציה שאנחנו קוראים לה ומה שהפונקציה הזאת עושה זה אומרת בכל ריקווסט אם יש קובץ שמגיע בריקווסט עצמו, מקום מיוחד ברקוויסט שמתאים לקבצים, אז הפקודה הזאת לוקחת את
הקובץ ושותלת אותו ברקוויסט עצמו, טוב, אין לי פה משתנה של רקוויסט, תכף יענו, ברקוויסט נקודה פיילס. בי דיפולט אין שום דבר כזה.
אז זה מה שהפקודה עושה. אז כל מה שאנחנו צריכים לעשות, בואו רגע טיפה נצמצם פה בצורה כזאת, זה להגיד את הדבר הבא: אם היוזר גולש על ידי פוסט כי הרי הוא רוצה לשלוח לנו איזה משהו איזושהי תמונה נניח להוסיף איזה תמונה לבוא נניח upload image איזשהו ראוט
שאני כרגע ממציא אז זאת הפונקציה שתתבצע מקבלת request רספונס ואנחנו רוצים קודם כל לבדוק איזושהי ולידציה האם יש לנו תמונה בכלל אולי היוזר לא שלח שום דבר ומנסה לגלוש ל-upload image זה לא הגיוני אז אם אין שום דבר ב-request files בואו נשלח לו הודעת שגיאה response.status ההודעה
המתאימה היא 400 ונגיד לו no file or no image sent ונצא החוצה הנה יש לנו כרגע טיפול רק במצב של שגיאה הוא לא הגיוני שהוא יגלוש לי למקום שאומר לי אני רוצה להעלות לך תמונה בלי להביא לי את התמונה עצמה.
הדבר הבא שאנחנו רוצים לעשות זה לקבל את הקובץ שלו. מה הקובץ של התמונה שהוא שלח? אנחנו כרגע מטפלים במצב שהוא שולח לנו תמונה אחת בלבד Upload Image.
אז אנחנו רוצים לגשת ולקחת אובייקט שמתאר את כל הקובץ עצמו, זה לא רק השם שלו, זה כל הקובץ. ב-request files יש בעצם את הכובד של התמונה יושב באיזשהו משתנה שמוגדר על ידי ה-HTML אבל אנחנו עוד לא בנינו את ה-HTML אז אולי רגע בשלב הזה נעצור עם הפקודה הזאת אפילו שאני בדרך כלל לא אוהב לעצור ולחזור אבל אולי זה כן ייתן
הבנה יותר טובה מה המשתנה שאנחנו מחפשים פה. אנחנו נבנה כרגע את אינדקס html. באינדקס html אנחנו רוצים קודם כל סימן קריאה enter, upload images, ומה שאנחנו רוצים לעשות זה קודם כל איזושהי כותרת, upload images, למרות שבהתחלה אנחנו מעלים
תמונה אחת, אבל תכף נשנה את זה למספר תמונות. ויש לנו פה פורום, אולי נעשה את זה בצורה כזאת. Upload H2, התכוונתי, Single Image.
וזה הדבר הראשון, בוא תעלה תמונה אחת ויחידה. יש לנו פורום ואנחנו רוצים שהאקשן, כלומר לאן הפורום הזה גולש, אז הפורום גולש לראוט הזה.
בואו ניקח בדיוק את הראוט ונשים אותו פה. מתוד של הפורום זה פוסט ובשביל שהפורום יתמוך בהעלאת קבצים זה פיצ'ר של html שאנחנו צריכים להוסיף אנחנו חייבים לתת לו הגדרה שנקראת n-type ואנחנו צריכים לתת לו multi-part form data הפקודה הזאת אומרת ב html שאנחנו מעוניינים
שהטופס הזה יתמוך גם בהעלאת קבצים אם אין את הפקודה הזאת הטופס בכלל לא שולח קבצים בי דיפולט אז יש לנו תיבת input אנחנו רוצים לתת לה טייפ פייל ויש לנו איזשהו לחצן של Upload.
עכשיו אנחנו חייבים לתת Name בכדי שב-HTML המידע הזה אכן יישלח. פה ניתן לו את ה-Name MySingleImage. סתם שם שהמצאתי. השם הזה שאנחנו רואים פה זה השם שאנחנו צריכים לשים פה.
לכן רציתי שנייה אחת לעזוב, לבנות את ה-HTML בכדי להבין שכל דבר שאנחנו שולחים על ידי פורום צריך שיהיה לו name. וה-name זה בדיוק השם שאנחנו מחפשים כאן. לא משנה שאנחנו המצאנו את השם הזה.
זה בסדר, זה שם מומצא. עכשיו, מה יש לנו בפייל? בפייל יש לנו אובייקט שמתאר את התמונה עצמה. מה שאנחנו רוצים לעשות עכשיו זה פשוט לשמור אותה.
יש לנו את האובייקט פייל, ויש לו פונקציה שנקראת mv, קיצור של move. ואז הוא אומר לנו, טוב, לאן אתם רוצים שאני אשמור את התמונה? בואו נגיד לו שבתיקייה הנוכחית יושבת תיקיית uploads, ובתוכה אני רוצה לשמור את file.name, זה השם של התמונה.
אז דבר ראשון, אם אנחנו מריצים את זה ואין תיקיית upload, זה יכול להוות איזושהי בעיה. תכף נראה ונטפל בזה אבל הדבר הבא שאנחנו צריכים זה להחזיר משהו ליוזר אחרת הוא בכלל לא יצליח לקבל תשובה בחזרה בואו סתם נחזיר לו כרגע done או משהו כזה אפשר גם להפנות אותו לאיזה דף אחר אז אנחנו רוצים קודם כל לבדוק את זה
בואו נריץ node app בואו נריץ את האתר שלנו הנה הוא נפתח ויש לנו כאן, שים את זה פה בצד, בחירה של קובץ, ויש לנו פה תיקיית אימג'ז עם שלושה קבצים, בניז, קיטנס, פאפיז.
שימו לב שכל קובץ יש לו סיומת אחרת, png, jpeg, gif. בואו נבחר את בניז, נבצע אופן, הנה אנחנו רואים את בניז, Upload, ואנחנו מקבלים פה מאחור מעין קריסה כזאת.
אפילו שהוא כתב לנו done, הוא לא באמת הצליח לשמור. הוא אומר לנו, תשמעו, אין לי קובץ או דיירקטורי, וזה הגיוני, אין לנו תיקייה.
אז אנחנו יכולים לבנות כאן את התיקייה הזאת, את ה-uploads שאליה אנחנו רוצים לבצע את ההעלאה, אבל בואו נעשה משהו קצת יותר אלגנטי. מה שנעשה זה בתחילת הסרבר, פעם אחת בלבד, אנחנו רוצים לבצע בדיקה עם 0 נקודה.
אקזיסט סינק או ליתר דיוק נוט יש לי פה סימן קריאה נוט אקזיסט את אפלודס אם התיקייה הזאת לא קיימת מייק דיר סינק צור אותה דוט סלאש אפלודס למה בעצם יש לנו פה סינק ולא אסינק מפני שהדבר הזה בן קורץ פעם אחת בלבד כאשר השרת עולה לאוויר הפקודה הזאת לא רצה עבור כל לקוח אם היינו עושים את
הפקודה כאקזיסט כלומר אסינק אז היינו צריכים לטפל פה באסינק ואווייט ולעטוף את זה בפונקציה ולא כדאי להתעסק עם זה אם לא באמת צריך.
אין בעיה שפעם אחת השרת