Jak przesyłać, wyświetlać i zapisywać obrazy za pomocą node.js i express [zamknięte]

110

Muszę przesłać obraz i wyświetlić go, a także zapisać, aby nie stracić go, gdy odświeżę hosta lokalnego. Należy to zrobić za pomocą przycisku „Prześlij”, który zapyta o wybór pliku.

Używam node.js i Express dla kodu po stronie serwera.

user1602123
źródło
4
Zajrzyj do sekcji, FAQaby dowiedzieć się, jakie pytania należy tu zadać. Tak czy inaczej, tym razem odpowiem na twoje pytanie.
fardjad
103 użytkowników nie uważa, że ​​to pytanie jest niejednoznaczne, niejasne, niekompletne, zbyt szerokie lub retoryczne. Ciekawy. ;)
Andreas

Odpowiedzi:

251

Przede wszystkim powinieneś stworzyć formularz HTML zawierający element wejściowy pliku . Musisz również ustawić atrybut enctype formularza na multipart / form-data :

<form method="post" enctype="multipart/form-data" action="/upload">
    <input type="file" name="file">
    <input type="submit" value="Submit">
</form>

Zakładając, że formularz jest zdefiniowany w index.html przechowywanym w katalogu o nazwie public w stosunku do miejsca, w którym znajduje się twój skrypt, możesz go obsługiwać w ten sposób:

const http = require("http");
const path = require("path");
const fs = require("fs");

const express = require("express");

const app = express();
const httpServer = http.createServer(app);

const PORT = process.env.PORT || 3000;

httpServer.listen(PORT, () => {
  console.log(`Server is listening on port ${PORT}`);
});

// put the HTML file containing your form in a directory named "public" (relative to where this script is located)
app.get("/", express.static(path.join(__dirname, "./public")));

Gdy to zrobisz, użytkownicy będą mogli przesyłać pliki na Twój serwer za pośrednictwem tego formularza. Jednak aby ponownie złożyć przesłany plik w aplikacji, musisz przeanalizować treść żądania (jako dane formularza wieloczęściowego).

W Express 3.x można używać express.bodyParseroprogramowania pośredniego do obsługi formularzy wieloczęściowych, ale od Express 4.x nie ma analizatora treści dołączonego do frameworka. Na szczęście możesz wybrać jeden z wielu dostępnych parserów multipart / form-data . Tutaj użyję multera :

Musisz zdefiniować trasę do obsługi postów z formularzy:

const multer = require("multer");

const handleError = (err, res) => {
  res
    .status(500)
    .contentType("text/plain")
    .end("Oops! Something went wrong!");
};

const upload = multer({
  dest: "/path/to/temporary/directory/to/store/uploaded/files"
  // you might also want to set some limits: https://github.com/expressjs/multer#limits
});


app.post(
  "/upload",
  upload.single("file" /* name attribute of <file> element in your form */),
  (req, res) => {
    const tempPath = req.file.path;
    const targetPath = path.join(__dirname, "./uploads/image.png");

    if (path.extname(req.file.originalname).toLowerCase() === ".png") {
      fs.rename(tempPath, targetPath, err => {
        if (err) return handleError(err, res);

        res
          .status(200)
          .contentType("text/plain")
          .end("File uploaded!");
      });
    } else {
      fs.unlink(tempPath, err => {
        if (err) return handleError(err, res);

        res
          .status(403)
          .contentType("text/plain")
          .end("Only .png files are allowed!");
      });
    }
  }
);

W powyższym przykładzie, pliki .png przesłane do / upload zostaną zapisane w katalogu wgranym względem miejsca, w którym znajduje się skrypt.

Aby pokazać przesłany obraz, zakładając, że masz już stronę HTML zawierającą element img :

<img src="/image.png" />

możesz zdefiniować inną trasę w swojej aplikacji ekspresowej i użyć res.sendFiledo obsługi zapisanego obrazu:

app.get("/image.png", (req, res) => {
  res.sendFile(path.join(__dirname, "./uploads/image.png"));
});
fardjad
źródło
101
Pan jest dżentelmenem i uczonym
mattdlockyer
9
Dla każdego, kto chce uzyskać dostęp do „req.files” lub „req.body”, body-parser obsługuje teraz tylko JSON, sprawdź github.com/expressjs/multer
Scott Meyers
5
jako "app.use (express.bodyParser ({uploadDir: '...'}));" nie działa, należy użyć "app.use (bodyParser ({uploadDir: '...'}));". w tym celu należy dodać parser ciała przez npm i dodać do pliku, w którym go używasz, poprzez "var bodyParser = require ('body-parser');"
Niklas Zantner
4
jak możemy to zrobić w express 4?
Muhammad Shahzad
4
@fardjad A co, jeśli między nimi mam kąt?
Gaurav51289,