Multer 上传工作正常,但每隔几次尝试就会失败。好像异步不起作用

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

我正在开发一个应用程序,它使用 multer 中间件一次将多个文件存储到数据库中。我已完成所有设置并正常工作,但每隔几次尝试,我的上传就会失败,并且没有错误消息。它会上传文件,但不会保存到数据库,也不会生成错误消息。

下面是前端代码(表单和附带函数)

import React, { useState } from 'react'
import BackButton from '../components/BackButton';
import Spinner from '../components/Spinner';
import axios from 'axios';
import { useNavigate } from 'react-router-dom';

export const CreatePhoto = () => {

  const [category, setCategory] = useState({});
  const newFiles = [];
  const [files, setFiles] = useState({});
  const [loading, setLoading] = useState(false);
  const navigate = useNavigate(); 

  const handleChange = (e) => {
    setCategory(e.target.value);
    console.log(e.target.value);
  }

  const handlePhoto = (e) => {
    setFiles(e.target.files)
  }


  const handleSubmit = () => {
    console.log(files);
    const formData = new  FormData();
    formData.append('category', category);
    for (let i=0; i<files.length;i++){
      formData.append('photo', files[i]);
    }
    console.log(...formData);
    alert('Working for now, lets see how it goes!');
    setLoading(true);
    axios
      .post('http://localhost:5555/uploadImage', formData)
      .then(() => {
        alert("Checking ...");
        setLoading(false);
        navigate('/');
      })
      .catch((error) => {
        setLoading(false);
        alert('An error occured. Please check console!!');
        console.log(error);
      });
  };
  return (
    <div className='p-4'>
      <BackButton />
      <h1 className='text-3xl my-4'>Upload Photos</h1>
      {loading ? <Spinner /> : ''}

      <div className='flex flex-col border-2 border-sky-400 rounded-xl w-[600px] p-4 mx-auto'>
        <form onSubmit={handleSubmit} encType='multipart/form-data'>
          <div className='my-4'>
            <label className='mb-2 inline-block text-neutral-500 dark:text-gray-800' htmlFor='category'>Category</label>
              <select id="category" name="category"
              className='bg-gray-50 border-2 border-yellow-600 text-gray-900 text-base rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-100 dark:border-yellow-500 dark:placeholder-gray-400 dark:text-gray-800 dark:focus:ring-blue-500 dark:focus:border-blue-500'
              onChange={handleChange}>
                <option defaultValue={'Reception'}>Choose a Category</option>
                <option value="Traditional">Traditional</option>
                <option value="Court">Court</option>
                <option value="Reception">Reception</option>
              </select>
          </div>

          <div className='mb-3'>
            <label
              htmlFor="formFileMultiple"
              className='mb-2 inline-block text-neutral-500 dark:text-gray-800'
              >Upload Images</label>
            <input
              className='relative m-0 block w-full min-w-0 flex-auto cursor-pointer rounded border border-2 border-yellow-500 bg-gray-100 bg-clip-padding px-3 py-[0.32rem] text-base font-normal text-surface transition duration-300 ease-in-out file:-mx-3 file:-my-[0.32rem] file:me-3 file:cursor-pointer file:overflow-hidden file:rounded-none file:border-0 file:border-e file:border-solid file:border-inherit file:bg-transparent file:px-3  file:py-[0.32rem] file:text-surface focus:border-primary focus:text-gray-700 focus:shadow-inset focus:outline-none dark:border-yellow dark:text-black  file:dark:text-black'
              type="file"
              name="photo"
              onChange={handlePhoto}
              id="formFileMultiple"
              multiple="multiple" />
          </div>
          <button className='p-2 bg-sky-300 m-8' type='submit'>
            Upload
          </button>
        </form>
      </div>
    </div>
  )
}

export default CreatePhoto

这是后端代码

.
.
.
const fileStorage = multer.diskStorage({
    destination: 'images',
    filename : (request, file, cb) => {
        cb(null, file.fieldname + '_' + Date.now() + path.extname(file.originalname));
    }
});

const uploadImage =  multer({
    storage : fileStorage,
    limits : {
        fileSize: 10000000
    },
    fileFilter(request, file, cb) {
        if (!file.originalname.match(/\.(png|jpg|jpeg)$/)) {
            return cb(new Error('Please upload an Image file!'));
        }
        cb(undefined, true);
    }
});

app.post('/uploadImage', uploadImage.array('photo', 20), async (request, response) => {
    

    const files = request.files;
    console.log(request.body);
    console.log(request.files);
    const imgArray =  await files.map((file) => {
        const img = fs.readFileSync(file.path);

        return img.toString('base64');
    });
    imgArray.map(async (src, index) => {
        const finalImg = {
            title : files[index].originalname,
            path : files[index].path,
            fileSize : files[index].size,
            category : request.body.category
        }
        console.log();
        const newUpload = new Photo(finalImg);


        try {
            await newUpload.save();
            console.log("Upload was good");
            response.json('Upload was successful!!');
        } catch (error) {
            response.status(400).json({error:error.message || `Something went wrong somewhere`});
        }
        });
});

我尝试将 post 请求设为异步,因为我的想法是由于数据库连接问题而遇到了延迟;也许连接速度慢或类似的东西。所以我认为使用异步可以解决问题,但我不太确定我是否有效地使用了它,或者在这种情况下它是否没有帮助。

我期望的功能是所有上传命令都成功,或者如果有原因导致上传无法正常工作,我会生成一条特定的错误消息。

reactjs node.js mongodb mern multer
1个回答
0
投票

将await与async一起使用不会产生任何效果,因为

await
将阻塞异步函数并等待作业完成(直到promise解析)。

同样在您的情况下,使用

.map
函数是错误的,它用于创建新数组。您可以使用
.forEach
来代替。

无论哪种方式,在循环中,一旦第一个项目被处理,它都会向客户端发送响应,这将中断服务器请求并停止进程。

所以我建议使用 Promise 并行处理所有图像。

app.post('/uploadImage', uploadImage.array('photo', 20), async (request, response) => {
    try {
        const files = request.files;

        const promises = files.map((file) => {
            return new Promise(async (resolve) => {
                // const img = fs.readFileSync(file.path);
                // const imgBase64 = img.toString('base64');

                const finalImg = {
                    title: file.originalname,
                    path: file.path,
                    fileSize: file.size,
                    category: request.body.category
                };

                const newUpload = new Photo(finalImg);

                await newUpload.save();
                resolve('Upload was good');
            });
        });

        await Promise.all(promises);

        response.json('Upload was successful!!');
    } catch (error) {
        response.status(500).json({ error: error });
    }
});

希望这有帮助!

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