קורס Node.JS שיעור הוספת תמונה לכל פוסט בלוח המודעות


זה נושא דיון מלווה לערך המקורי ב- https://www.tocode.co.il/bundles/nodejs/lessons/39-demoapp-3

שלום ובוקר טוב.
רציתי לשאול איך אפשר לקבל את כל הdocuments מהמודול וכן את כל הפרטים בכל מסמך?
ניסיתי בעזרת : const inv = await invstor.find({});
אבל הוא מחזיר לי מערך ואין אופציה לעשות to array .
עד כאן זה כשאני מחזיר ב res.end.
אם אני מחזיר ב res.send הוא נותן לי את הכל אבל התמונה ב buffer ולא כתמונה.
אשמח לשמוע תשובה בתודה מראש:)

הי אני לא לגמרי מבין - מה הכוונה התמונה ב buffer ולא כתמונה?

מה שאתה צריך בשביל לקבל את התמונה זה בסך הכל את ה ID שלה. אז ב HTML משתמשים באלמנט img עם הנתיב לתמונה כדי לקבל את התמונה עצמה

הכוונה כך: אני משתמש בvue.js
ולכן אני לא שולח בצורה של res.render
כשאני מנסה לשלוח רק תמונה כמו שהראית בסרטון הכל מעולה, אבל אני רוצה לשלוח לא רק את התמונה אלא גם את כל הנתונים של אותו משתמש, ולא רק זה אלא של כל המשתמשים, לדוגמה עבור להציג למנהל האתר את כל המשתמשים.
הצורה היחידה שאני מצליח לשלוח תמונה ושיהיה על המסך תמונה זה ב res.end
אבל בזה אם אני מנסה לשלוח את כל הפרטים הוא כותב לי שלא ניתן לשלוח גם טקסט וגם buffer
אם אני מנסה לשלוח ב res.send
הוא נותן לי את הכל אבל את התמונה לא כתמונה אלא כbuffer
אולי הפיתרון להפוך בצד הלקוח מבאפר לתמונה א"כ אשמח לשמוע איך עושים את זה.
ינון ממש תודה על ההתיחסות הנפלאה ותודה מראש על כל תשובה.
מצטער על הירידת שורה זה כדי שהאנגלית לא תשבש את הקריאה.

ממה שאני מכיר תצטרך להפריד את הקוד שלך לכמה בקשות, כלומר בבקשת ה AJAX הרגילה לקבל JSON עם כל הפרטים, אחד מהפרטים יהיה ה URL לתמונה ואז בבקשה אחרת חדשה תפנה לנתיב של התמונה כדי למשוך אותה.

כשמה שחשוב שאת התרגום מ״נתיב לתמונה״ ל״תמונה ממש״ אתה לא באמת צריך לכתוב אלא פשוט יוצר אלמנט img שה src שלו הוא הנתיב לתמונה שמצאת
(כלומר אין היגיון בלשלוח את ה Buffer עצמו בתוך ה JSON. מה שצריך להעביר ללקוח זה נתיב לתמונה)

קודם כל תודה רבה ינון שאתה עונה זה לא מובן מאליו, וזה אחד הסיבות שנרשמתי לאתר…
אני לא מדבר על תמונות ששוכבות אצלי בספריה, ואני שומר בבסיס נתונים רק את הנתיב,
אלא על תמונה שקיבלתי מהמשתמש כמו אצלך בישום ואני מעוניין להציג אותה יחד עם עוד פרטים ששמורים יחד באותו מסמך בבסיס הנתונים.

זה בדיוק אותו דבר

מבחינת השרת כשמגיעה בקשה לדוגמא ל:

/images/profile.png

השרת מחליט אם להוציא את הקובץ ממערכת הקבצים או אם להעביר את זה לטיפול של Express ולהוציא את הקובץ מבסיס הנתונים. אבל מבחינת הקלאיינט זה לא משנה מאיפה התמונה מגיעה הדבר היחיד שהוא צריך זה נתיב לתמונה

נסה להסתכל בכל אתר ברשת שאתה מכיר ותלחץ כפתור ימני על תמונה ו Inspect Element מהדפדפן ואתה תראה שיש שם אלמנט img עם נתיב למשהו שנראה כמו קובץ על השרת.

הלקוח מקבל JSON עם מידע על התמונה כולל הפרטים והנתיב אליה ושותל אותו בעמוד ה HTML,
הדפדפן לוקח את אלמנט ה img שנוצר ופונה שוב לשרת כדי לקחת את התמונה עצמה

אני מתנצל על ההטרחה, אבל כשאני מוציא buffer מבסיס נתונים, מאיפה אני יביא נתיב לתמונה?
הצורה לגשת לבסיס נתונים היא רק דרך קריאה בצד ה-server לבסיס נתונים, ובצד הלקוח הדרך היחידה לקבל נתונים מהשרת זה על ידי ajax ודומיו, אז איזה נתיב אני יכול לתת ל- img src.
הצורה היחידה בה הצלחתי להציג תמונות היא כשאני שומר בספרייה של צד הלקוח תמונות ואז יש לי נתיב ברור.
כנראה שיש משהו שאני לא יודע שאתה מתכוון אליו, אם תוכל להסביר לי קצת יותר, אני בטוח שאני הטמבל כאן.
תודה מראש.

שים לב לקוד הבא מתוך קוד השרת:

router.get('/img/:id', async function(req, res, next) {
    const post = await Post.findById(req.params.id);
    res.end(post.image);
});

זה אומר שאם יש לך Image ID יש לך את הנתיב, לדוגמא אם מזהה התמונה הוא 7 הנתיב לתמונה יהיה:

/img/7

אני יודע שבדרך כלל אנחנו רגילים לראות נתיבים לתמונה שמסתיימים בסיומת כמו png או jpg, אבל זה באמת לא משנה מבחינת התקשורת מה תהיה הסיומת.

תודה רבה ינון.
אני מבין שהבעיה שלי היא לא בצד השרת, אלא בצד הקליינט,
איך אני מציג בתגית img src נתיב לתמונה משרת, ולא מהספריה.
ואני אשבור את הראש איך אני מציג את זה שם.

בכל מקרה תודה על התשובה. :pray:

שלום ינון. הצלחתי לשמור תמונה בדאטה בייס כחלק מcard אבל אני לא מצליח להציג אותה בצד הלקוח בתוך הcard. האם הנתיב שונה כשהתמונה היא חלק מהcard? האם יש הבדל בין השימוש בhtml רגיל לשימוש בreact? כי אני פשוט לא מצליח להציג את התמונה בנתיב הזה…

תודה רבה.

הי @11134,

יכול להדביק פה מה ניסית לעשות? בגדול מה שצריך:

  1. ליצור נתיב בשרת שיקרא את התמונה מבסיס הנתונים ויחזיר אותה
  2. בצד הלקוח ליצור אלמנט img שה href שלו מכוון לאותו נתיב

router.get("/my-cards", auth, async (req, res) => {

    if (!req.user.admin) return res.status(401).send("Access denied.");

    const cards = await Card.find({ user_id: req.user._id });

    res.send(cards);

הי

הנתיב הזה לא שולח תמונה אלא אוביקט כרטיס. זה מבלבל כי באמת שאר הדברים שבכרטיס נשלחים כמו שהם ומספיק הנתיב הזה.

עבור תמונה חשוב לייצר נתיב נפרד רק של תמונות כמו בדוגמה שלי כאן:

router.get('/img/:id', async function(req, res, next) {
    const post = await Post.findById(req.params.id);
    res.end(post.image);
});

ובטמפלייט היה לי את הקוד הזה שיוצר תמונה מתוך נתיב התמונות:

    <body>
        <a href='/posts/new'>New Message</a>
        <ul class="feed">
        <% for (let post of posts) { %>
            <li>
                <span class="author"><%= post.author %></span>                                
                <span class="text" style="color: <%= post.color %>"><%= post.text %></span>
                <% if (post.image) { %>
                    <img src="/posts/img/<%= post.id %>" />
                <% } %>
            </li>
        <% } %>
        </ul>
        <%- include('../pagination') %>
    </body>

יכול להדביק את המקבילה של זה בקוד שלך? ולתאר את ה flow ?

הצד לקוח שלי זה ריאקט ולא הבנתי עד הסוף איך לכתוב את זה בצורה שתתאים לריאקט אז כתבתי ככה:

export function getImage() {

  return http.get(`${apiUrl}/cards/img/:id`).
<img

          className="p-2"

          src= { getImage().travelImage}

          width="100%" height="200"

          alt={card.travelName}

        />

הי משהו בהדבקה נראה לא מדויק - חסר מה שאחרי הנקודה בפונקציה. אבל בכל מקרה זה לא נראה הגיוני.

יכול להדביק את כל הקומפוננטת ריאקט שכתבת?

דבר נוסף בצד השרת הנתיב apiUrl/cards/img/:id מחובר לתמונה? אתה יכול לנסות את זה עם ID לדוגמה בדפדפן ואתה רואה את התמונה של הכרטיס?

export function getImage() {

return http.get(${apiUrl}/cards/img/:id/);

}

import React from "react";

// import {apiUrl} from '../config.json'

import { getImage } from "../services/cardService";

const Card = ({ card }) => {

 

  return (

    <div className="col-md-6 col-lg-4 mt-3 text-right">

      <div className="card">

        <img

          className="p-2"

          src= { getImage().travelImage}

          width="100%" height="200"

          alt={card.travelName}

        />

        <div className="card-body">

          <h5 className="card-title">{card.travelName}</h5>

          <p className="card-text border-top pt-2">

            <b>למי הטיול? </b>

            {card.travelCategory}

            <br />

            <b>מקום מפגש:</b>

            {card.travelAddress}

          </p>

        </div>

      </div>

    </div>

  );

};

export default Card;

הוא מחובר, אבל לא מצליח לקבל את התמונה…

כן הבעיה בקוד ריאקט

נסה במקום ליצור img src פשוט לשים שם אלמנט p כלומר שורה כזאת:

<p>{ getImage().travelImage}</p>

הטקסט שמופיע צריך להיות URL שמוביל לתמונה. לדעתי הוא לא יהיה. אשמח לשמוע מה הטקסט שכן מופיע ולפי זה נוכל להתקדם ולראות מה הבעיה