使用 Express 和 Multer 中间件的 NodeJS 应用程序不会将图像文件保存到磁盘

问题描述 投票:0回答:1

我正在努力让这个示例代码正常工作。我对本示例中使用的所有技术都很陌生,所以我也不知道要采取哪些步骤来尝试和调试。我尝试添加一些

console.log
日志记录,但也未能做到这一点。

这是服务器端代码:

const express = require("express");
const multer = require("multer");
const cors = require("cors"); // why is this needed? I tried to find out but still don't understand what it does
const fs = require("fs");

const app = express();
const port = 3000;
app.use(express.json());
app.use(cors()); // what does it do?

const storage = multer.diskStorage({
  destination: (request, file, cb) => {
    cb(null, "uploads_test/"); // should be saving to `./uploads_test/` if I understand correctly, the folder does exist
  },
  filename: (request, file, cb) => {
    cb(null, file.fieldname + "-" + Date.now() + ".jpg");
  },
});

const upload = multer({ storage: storage });

app.post("/upload", upload.single("image"), async (request, response) => {
  try {
    await fs.promises.mkdir("uploads_test", { recursive: true });

    // none of this appeared to be helpful
    //console.log(request.body);
    //console.log(request.body.formData);
    // this just didn't work
    //console.log(request.body.formData[0]);

    response.status(200).json({
      message: "image upload success",
      file: request.file,
    });
  } catch (error) {
    console.error("Error handling image upload:", error.message);

    // Send a response indicating failure
    response.status(500).json({ error: "Internal Server Error" });
  }
});

async function main() {
  if (!fs.existsSync("uploads_test")) {
    fs.mkdirSync("uploads_test");
  }

  app.listen(port, () => {
    console.log(
      `server imageServer (example) is listening at http://localhost:${port}`
    );
  });
}

main().catch((error) => {
  console.error(error);
});

这是 React-Native 端代码:

import React, { useState, useEffect } from "react";
import { View, Text, Image, Button, StyleSheet } from "react-native";
import * as ImagePicker from "expo-image-picker";
import axios from "axios";

const ImageUploadScreenExpo = () => {
  const [hasGallaryPermissions, setHasGalleryPermissions] = useState(null);
  const [selectedImage, setSelectedImage] = useState(null);

  useEffect(() => {
    (async () => {
      const galleryStatus = await ImagePicker.requestCameraPermissionsAsync();
      setHasGalleryPermissions(galleryStatus.status === "granted");

      if (galleryStatus.status !== "granted") {
        alert("permission denied");
      }
    })();
  }, []);

  const handleImageUploadAsync = async () => {
    if (!selectedImage) {
      alert("Please select an image first");
      return;
    }

    const fileExtension = selectedImage.split(".").pop();
    const fileType = `image/${fileExtension}`;

    const formData = new FormData();
    formData.append("image", {
      uri: selectedImage,
      type: fileType,
      name: `image.${fileExtension}`,
    });

    try {
      const response = await axios.post("http://192.168.0.11:3000/upload", {
        formData,
        headers: {
          "Content-Type": "multipart/form-data",
        },
      });

      // I keep seeing this in the logs, but the image is not saved
      console.log("Image uploaded successfully:", response.data);
    } catch (error) {
      console.error(error);
    }
  };

  const selectImageAsync = async () => {
    let result = await ImagePicker.launchImageLibraryAsync({
      mediaTypes: ImagePicker.MediaTypeOptions.Images,
      allowsEditing: true,
      aspect: [1, 1],
      quality: 1,
    });

    if (!result.canceled) {
      setSelectedImage(result.assets[0].uri);
    } else {
      alert("no image selected");
    }
  };

  if (hasGallaryPermissions === false) {
    return <Text>No access to Internal Storage</Text>;
  }

  return (
    <View style={styles.container}>
      <Text>Select an image to upload:</Text>
      <Button title="Select Image" onPress={selectImageAsync} />
      <Button title="Upload Image" onPress={handleImageUploadAsync} />
      {selectedImage && (
        <View style={styles.imageContainer}>
          <Image
            source={{ uri: selectedImage }}
            style={{ width: 200, height: 200 }}
          />
        </View>
      )}
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "white",
    alignItems: "center",
    justifyContent: "center",
  },
});

export default ImageUploadScreenExpo;
就任何日志记录和错误而言,一切似乎都工作正常,但没有图像被保存到服务器目录中。我似乎无法弄清楚为什么会出现这种情况,而且我也不知道从哪里开始调试。例如,如果我要在服务器端的某个位置添加一些日志记录来检查图像的数据是否确实存在,我将如何去做?

我之前尝试过使用expressjs和multer制作头像上传功能。所以我认为我的代码可以为您提供有用的参考。我会放在下面。
reactjs node.js react-native expo multer
1个回答
0
投票
上传中间件(uploadAvatar.js)

const multer = require("multer"); const fs = require("fs"); const home = __dirname.replace("middlewares","") + "uploads"; const diskStorage = multer.diskStorage({ destination: function (req, file, callback) { let userUID = req.user.UID; let userUploadPath = home + `/${userUID}` if(!fs.existsSync(userUploadPath)) { fs.mkdirSync(userUploadPath, {recursive: true}) } callback(null, userUploadPath) }, filename: function (req, file, callback) { let acceptMimeType = ["image/png", "image/jpeg","image/jpg","image/tiff"] if(acceptMimeType.indexOf(file.mimetype) === -1) { let errorContent = "This file type is not supported." callback(errorContent, null) } let filename = "avatar.png" callback(null, filename) } }); const uploadAvatar = multer({ storage: diskStorage,overwrite: true, limits:{fileSize: 3*1024*1024}}).single("userAvatar"); module.exports = uploadAvatar

接收上传头像路由(userRoute.js)
const express = require('express');
const router = express.Router();
const userController = require("../controllers/userController");

router.route("/upload/avatar")
.post(userController.updateAvatar)

处理上传头像(userController.js)
const uploadProfilePicutre = require("../middlewares/uploadAvatar");
const User = require("../models/User");
const path = require("path");
const userController = {
     updateAvatar: async(req,res,next)=>{
        try {
            await uploadProfilePicutre(req, res, (error,filename) => {

                if (error) {
                    
                    if(error.code == 'LIMIT_FILE_SIZE')
                    {
                        return res.status(400).json({message:"File size must less than 3MB."});
                    }
                    
                    return res.status(400).json({message:`${error}`});
                }

                let avatarPath = req.file.path.substring(req.file.path.indexOf("\\uploads")).split("\\")
                let realPath = avatarPath.join("/").replace("/uploads","").replace("/app","")
                
                User.findOne({UID: req.user.UID})
                .then(userAccount => {

                    if(!userAccount)
                    {
                        throw new Error("Account does not exist");
                    }
                    else
                    {
                        userAccount.avatar = realPath
                        userAccount.save();
                    }

                })


                return res.status(200).json({message:"Update avatar successfully."});

            })
        } catch (error) {

            return res.status(400).json({message:`${error}`});
        }
        
    }
}
module.exports = userController


© www.soinside.com 2019 - 2024. All rights reserved.