为什么我在Nextjs中上传文件时会出现此错误

euoag5mw  于 2023-06-29  发布在  其他
关注(0)|答案(2)|浏览(287)

我做了一个小项目,需要一个csv文件,并上传它。然后处理其内容以填充mongodb集合
我犯了这两个错误:
在VS代码控制台中:

API resolved without sending a response for /api/upload, this may result in stalled requests.

在Web App中:

Unhandled Runtime Error
Error: Objects are not valid as a React child (found: object with keys {storageErrors}). If you meant to render a collection of children, use an array instead.

Call Stack
throwOnInvalidObjectType
node_modules\react-dom\cjs\react-dom.development.js (14887:0)
createChild
node_modules\react-dom\cjs\react-dom.development.js (15139:0)
reconcileChildrenArray
node_modules\react-dom\cjs\react-dom.development.js (15404:0)
reconcileChildFibers
node_modules\react-dom\cjs\react-dom.development.js (15821:0)
reconcileChildren
node_modules\react-dom\cjs\react-dom.development.js (19167:0)
updateHostComponent
node_modules\react-dom\cjs\react-dom.development.js (19924:0)
beginWork
node_modules\react-dom\cjs\react-dom.development.js (21618:0)
HTMLUnknownElement.callCallback
node_modules\react-dom\cjs\react-dom.development.js (4164:0)
Object.invokeGuardedCallbackDev
node_modules\react-dom\cjs\react-dom.development.js (4213:0)
invokeGuardedCallback
node_modules\react-dom\cjs\react-dom.development.js (4277:0)
beginWork$1
node_modules\react-dom\cjs\react-dom.development.js (27451:0)
performUnitOfWork
node_modules\react-dom\cjs\react-dom.development.js (26557:0)
workLoopSync
node_modules\react-dom\cjs\react-dom.development.js (26466:0)
renderRootSync
node_modules\react-dom\cjs\react-dom.development.js (26434:0)
performConcurrentWorkOnRoot
node_modules\react-dom\cjs\react-dom.development.js (25738:0)
workLoop
node_modules\scheduler\cjs\scheduler.development.js (266:0)
flushWork
node_modules\scheduler\cjs\scheduler.development.js (239:0)
MessagePort.performWorkUntilDeadline
node_modules\scheduler\cjs\scheduler.development.js (533:0)

这是我在Nextjs中的前端和API代码:

前端

import { useState } from 'react';

const IndexPage = () => {
  const [selectedFile, setSelectedFile] = useState(null);
  const [uploading, setUploading] = useState(false);
  const [message, setMessage] = useState(null);
  const [error, setError] = useState(null);

  const handleFileChange = (event) => {
    setSelectedFile(event.target.files[0]);
  };

  const handleFileUpload = async () => {
    if (!selectedFile) {
      setError('Please select a file');
      return;
    }

    setError(null);
    setMessage(null);
    setUploading(true);

    const formData = new FormData();
    formData.append('file', selectedFile);

    try {
      const response = await fetch('/api/upload', {
        method: 'POST',
        body: formData,
      });

      const data = await response.json();

      if (response.ok) {
        setMessage(data.message);
      } else {
        setError(data.error);
      }
    } catch (error) {
      setError('Something went wrong');
    } finally {
      setUploading(false);
    }
  };

  return (
    <div>
      <h1>File Upload</h1>

      <input
        name="file"
        type="file"
        accept=".csv"
        onChange={handleFileChange}
      />

      <button
        onClick={handleFileUpload}
        disabled={uploading}
      >
        {uploading ? 'Uploading...' : 'Upload'}
      </button>

      {message && <p>{message}</p>}
      {error && <p>Error: {error}</p>}
    </div>
  );
};

export default IndexPage;

这是后端

// pages/api/upload.js

import multer from 'multer';
import csv from 'csv-parser';
import fs from 'fs';
import { MongoClient, ObjectId } from 'mongodb';

const upload = multer({
  dest: 'uploads/', // Directory to store uploaded files
  limits: {
    fileSize: 5 * 1024 * 1024, // Limit file size to 5MB
  },
  fileFilter: (req, file, cb) => {
    if (file.mimetype !== 'text/csv') {
      cb(new Error('Only CSV files are allowed'));
    } else {
      cb(null, true);
    }
  },
});

const saveDistinctValues = async (collectionName, distinctValues) => {
  const client = new MongoClient('mongodb://0.0.0.0:27017/testcsv');
  try {
    await client.connect();
    const db = client.db();
    const collection = db.collection(collectionName);
    await collection.insertMany(distinctValues.map((value) => ({ value })));
  } finally {
    await client.close();
  }
};

const establishRelationships = async () => {
  const client = new MongoClient(process.env.MONGODB_URI);
  try {
    await client.connect();
    const db = client.db();
    const masterCategoryCollection = db.collection('master_category');
    const subCategoryCollection = db.collection('sub_category');
    const productGroupCollection = db.collection('product_group');
    const productCollection = db.collection('product');

    const masterCategories = await masterCategoryCollection.find().toArray();

    for (let i = 0; i < masterCategories.length; i++) {
      const masterCategory = masterCategories[i];
      const subCategory = await subCategoryCollection.findOne({
        value: masterCategory.value,
      });

      const productGroup = await productGroupCollection.findOne({
        value: subCategory.value,
      });

      const products = await productCollection
        .find({
          subCategoryId: { $exists: false },
          masterCategoryId: masterCategory._id,
        })
        .toArray();

      for (let j = 0; j < products.length; j++) {
        const product = products[j];
        await productCollection.updateOne(
          { _id: product._id },
          {
            $set: {
              subCategoryId: subCategory._id,
              productGroupId: productGroup._id,
            },
          }
        );
      }
    }
  } finally {
    await client.close();
  }
};

const handler = async (req, res) => {
  try {
    await upload.single('file')(req, res, async (error) => {
      if (error instanceof multer.MulterError) {
        // Multer error occurred during file upload
        res.status(400).json({ error: error.message });
      } else if (error) {
        // Other errors occurred
        res.status(500).json({ error: 'Something went wrong', error });
      } else if (!req.file) {
        // No file was provided
        res.status(400).json({ error: 'No file uploaded' });
      } else {
        const filePath = req.file.path;
        const masterCategories = [];
        const subCategories = [];
        const productGroups = [];
        const products = [];

        fs.createReadStream(filePath)
          .pipe(csv())
          .on('data', (row) => {
            const masterCategory = row.master_category.trim();
            const subCategory = row.sub_category.trim();
            const productGroup = row.product_group.trim();
            const product = row.product.trim();

            if (masterCategory !== '') {
              masterCategories.push({ value: masterCategory });
            }
            if (subCategory !== '') {
              subCategories.push({ value: subCategory });
            }
            if (productGroup !== '') {
              productGroups.push({ value: productGroup });
            }
            if (product !== '') {
              products.push({ value: product });
            }
          })
          .on('end', async () => {
            // Save distinct values to collections
            await saveDistinctValues('master_category', masterCategories);
            await saveDistinctValues('sub_category', subCategories);
            await saveDistinctValues('product_group', productGroups);
            await saveDistinctValues('product', products);

            // Establish relationships between collections
            await establishRelationships();

            res
              .status(200)
              .json({ message: 'File uploaded and processed successfully' });
          })
          .on('error', (error) => {
            console.error('Error processing CSV:', error.message);
            res.status(500).json({ error: 'Something went wrong' });
          });
      }
    });
  } catch (error) {
    console.error('Error uploading file:', error.message);
    res.status(500).json({ error: 'Something went wrong' });
  }
};

export default handler;

我无法理解这个错误,因为我是Next和React的新手。我已经环顾四周,我相信问题是与我使用组件的方式!

0qx6xfy6

0qx6xfy61#

出现此错误是因为您试图显示错误,该错误为Object
在这种情况下,您可以检查从后端得到的错误,并显示相关的错误消息。(如果有setError(data.error);
或者
出于测试目的,您可以简单地将错误显示为对象,如下所示:

{error && <p>Error: {JSON.stringify(error)}</p>}
mcvgt66p

mcvgt66p2#

您的React应用程序出错,因为您试图显示的error值是一个对象-您不能直接将对象放入JSX中。
error是一个对象可能来自这一行,在这一行中,您使用了两次键error,第二个示例用Error对象覆盖了第一个示例。

else if (error) {
    // Other errors occurred
    res.status(500).json({ error: 'Something went wrong', error });

相关问题