• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Problem z GridFSBucket

Object Storage Arubacloud
0 głosów
336 wizyt
pytanie zadane 16 maja 2020 w JavaScript przez Allen Obywatel (1,010 p.)

Próbuję użyć gridfs do uploadu zdjęć na stronę. W trakcie pisania kodu w konsoli pojawił mi się taki komunikat:

GridStore is deprecated, and will be removed in a future version. Please use GridFSBucket instead.

Muszę ten kod 

let gfs;
conn.once('open', () => {
  gfs = Grid(conn.db, mongoose.mongo);
  gfs.collection('uploads');
});

const storage = new GridFsStorage({
  url: mongoURI,
  file: (req, file) => {
    return new Promise((resolve, reject) => {
      crypto.randomBytes(16, (err, buf) => {
        if (err) { return reject(err) };
        const filename = buf.toString('hex') + path.extname(file.originalname);
        const fileInfo = {
          filename: filename,
          bucketName: 'uploads'
        };
        resolve(fileInfo);
      });
    });
  }
});

const upload = multer({ storage });

Zastąpić odpowiednikiem z gridfs bucket, więc napisałem to:

let gfb;
conn.once('open', () => {
  gfb = Grid(conn.db, mongoose.mongo);
  gfb.collection('uploads');
});

const bucket = new mongoose.GridFSBucket({
  url: mongoURI,
  file: (req, file) => {
    return new Promise((resolve, reject) => {
      crypto.randomBytes(16, (err, buf) => {
        if (err) { return reject(err) };
        const filename = buf.toString('hex') + path.extname(file.originalname);
        const fileInfo = {
          filename: filename,
          bucketName: 'uploads'
        };
        resolve(fileInfo);
      });
    });
  }
});

W tym miejscy pojawia się błąd:

mongoose.GridFSBucket is not a constructor.

Jak mam poprawić napisany kod lub jak poprawnie napisać go od nowa?

 

komentarz 16 maja 2020 przez ScriptyChris Mędrzec (190,190 p.)

Skoro powinieneś użyć GridFSBucket zamiast GridStore, to dlaczego użyłeś mongoose.GridFSBucket? W dokumentacji jest funkcja GridFSBucket, więc po co próbujesz jej użyć jako metody obiektu mongoose?

komentarz 16 maja 2020 przez Allen Obywatel (1,010 p.)
Próbowałem postępować analogicznie do poprzedniego przykładu. Teraz napisałem samo new GridFSBucket i w konsoli pojawia się to samo ostrzeżenie:

GridStore is deprecated, and will be removed in a future version. Please use GridFSBucket instead.

Dodatkowo występuje błąd:

MongoError: no chunks found for file, possibly corrupt.
komentarz 16 maja 2020 przez ScriptyChris Mędrzec (190,190 p.)
Jeśli mimo użycia zalecanej funkcji pokazuje się ostrzeżenie o użyciu zdeprecjonowanej wersji, to upewnij się że w przeglądarce jest świeża wersja kodu (mogło się coś zcache'ować). Przy ostrzeżeniu powinien być odnośnik do skryptu - kliknij w niego i postaw breakpoint, zobaczysz dlaczego takie ostrzeżenie się pojawia.
komentarz 16 maja 2020 przez Allen Obywatel (1,010 p.)

Wyczyściłem cache, ale nic to nie pomogło. Pojawiły się taki błędy:

To mój pierwszy projekt i większości nie rozumiem. Podejrzewam że błąd o niezdefiniowaniu <%files%> w library.ejs bezpośrednio wpływa na kolejne błędy. Proszę o pokierowanie lub wytłumaczenie co może być przyczyną problemów. Udostępniam fragment kodu z pliku library.ejs:

<div class="books-list">
            <% if(files){ %>
                <% files.forEach(function(file) { %>
                  <div class="card">
                    <% if(file.isImage) { %>
                      <img src="image/<%= file.filename %>" alt="">
                      <% } else { %>
                        <%= file.filename %>
                          <% } %>
                            <form method="POST" action="/files/<%= file._id %>?_method=DELETE">
                              <button class="btn-img-delete">Delete</button>
                            </form>
                  </div>
                  <% }) %>
                    <% } else { %>
                      <p>No files to show</p>
                      <% } %>
</div>

oraz z app.js:

let gfb;
conn.once('open', () => {
  gfb = Grid(conn.db, mongoose.mongo);
  gfb.collection('uploads');
});

const bucket = new GridFSBucket({
  url: mongoURI,
  file: (req, file) => {
    return new Promise((resolve, reject) => {
      crypto.randomBytes(16, (err, buf) => {
        if (err) { 
          console.log(err);
          return reject(err) };
        const filename = buf.toString('hex') + path.extname(file.originalname);
        const fileInfo = {
          filename: filename,
          bucketName: 'uploads'
        };
        resolve(fileInfo);
      });
    });
  }
});

const upload = multer({ bucket });

app.get('/library', (req, res) => {
  gfb.files.find().toArray((err, files) => {
    if (!files || files.length === 0) {
      res.render('library', { files: false });
    } else {
      files.map(file => {
        if (file.contentType === 'image/jpeg' || file.contentType === 'image/png') {
          file.isImage = true;
        } else {
          file.isImage = false;
        }
      });
      res.render('library', { files: files });
    }
  });
});

app.get('/files', (req, res) => {
  gfb.files.find().toArray((err, files) => {
    if (!files || files.length === 0) {
      console.log(err);
      return res.status(404).json({
        err: 'No files exist'
      });
    }
    return res.json(files);
  });
});

app.get('/files/:filename', (req, res) => {
  gfb.files.findOne({ filename: req.params.filename }, (err, file) => {
    if (!file || file.length === 0) {
      console.log(err);
      return res.status(404).json({
        err: 'No file exists'
      });
    }
    return res.json(file);
  });
});

app.get('/image/:filename', (req, res) => {
  gfb.files.findOne({ filename: req.params.filename }, (err, file) => {
    if (!file || file.length === 0) {
      console.log(err);
      return res.status(404).json({
        err: 'No file exists'
      });
    }

    if (file.contentType === 'image/jpeg' || file.contentType === 'image/png') {
      const readstream = gfb.createReadStream(file.filename);
      readstream.pipe(res);
    } else {
      console.log(err);
      res.status(404).json({
        err: 'Not an image'
      });
    }
  });
});

app.delete('/files/:id', (req, res) => {
  gfb.remove({ _id: req.params.id, root: 'uploads' }, (err, gridFSBucket) => {
    if (err) {
      console.log(err);
      return res.status(404).json({ err: err });
    }
    res.redirect('/library');
  });
});

app.get('/', (req, res) => res.render('index'));
app.get('/add', (req, res) => res.render('add'));
app.get('/library', (req, res) => res.render('library'));

app.post('/add', (req, res) => res.render('add'));
app.post('/library', (req, res) => res.render('library'));

app.post('/upload', upload.single('myCover'), (req, res) => {
  //res.json({ file: req.file });
  res.redirect('/library');
});

 

komentarz 16 maja 2020 przez ScriptyChris Mędrzec (190,190 p.)

Wstawione screeny są słabo nieczytelne - udostępnij je proszę np. przez imgur.com.

komentarz 16 maja 2020 przez ScriptyChris Mędrzec (190,190 p.)

Skąd konkretnie pochodzi zmienna/property files (ta, której dotyczy błąd)?

komentarz 16 maja 2020 przez Allen Obywatel (1,010 p.)
komentarz 16 maja 2020 przez Allen Obywatel (1,010 p.)

@JSHolic, Z 31 lub 40 linii kodu a app.js  z poprzedniego komentarza

komentarz 16 maja 2020 przez ScriptyChris Mędrzec (190,190 p.)

Kod w liniach 31 i 40 korzysta ze zmiennej files przekazanej jako argument do callbacka:

  gfb.files.find().toArray((err, files) => {

Skąd metoda gfb.files.find bierze dane i co zwraca (wypisz wynik jej wywołania w konsoli)? Jeśli pobiera z zewnątrz, to może być problem z brakiem danych po "drugiej stronie".

Swoją drogą w 30 linii jest if, który sprawdza, czy zmienna files jest falsy (przypadek obejmujący undefined) lub jest pustą tablicą:

    if (!files || files.length === 0) {

i w takim przypadku robi jakieś "czary mary":

res.render('library', { files: false });

Jeśli to przekazuje zmienną do wyrenderowania, to IMO zmienna files powinna mieć wartość false a nie undefined.

Chociaż, jeśli masz błąd, że files is not defined na ifie:

<% if(files){ %>

to znaczy, że takiej zmiennej w ogóle nie ma zadeklarowanej, co jest dziwne biorąc pod uwagę ciało callbacka z linii 30-41.

Nie wiem w czym tkwi problem... trzeba debugować skąd biorą się dane do zmiennej files i czy są do niej prawidłowo przypisywane. :)

komentarz 16 maja 2020 przez Allen Obywatel (1,010 p.)

Files to tablica wcześniej załadowanych zdjęć do wyświetlenia w library.ejs i jest to wynik dzałania funkcji w linii 45

app.get('/files', (req, res) => {
  gfb.files.find().toArray((err, files) => {
    if (!files || files.length === 0) {
      console.log(err);
      return res.status(404).json({
        err: 'No files exist'
      });
    }
    return res.json(files);
  });
});

Gdy files jest pustą tablicą lub undefined, to chcę wyrenderować library.ejs z files ustawionym na false, po to aby zdjęcia nie były wyświetlane. Wydaje mi się że źle napisałem żądania i odpowiedzi serwera. Jutro będę dochodził, co jest nie tak. Dzięki za poświęcony czas.

Zaloguj lub zarejestruj się, aby odpowiedzieć na to pytanie.

Podobne pytania

+1 głos
2 odpowiedzi 554 wizyt
0 głosów
1 odpowiedź 387 wizyt
0 głosów
1 odpowiedź 1,054 wizyt
pytanie zadane 22 lutego 2018 w JavaScript przez sosick Nowicjusz (160 p.)

92,573 zapytań

141,423 odpowiedzi

319,648 komentarzy

61,959 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...