代码之家  ›  专栏  ›  技术社区  ›  Stinny

使用reactjs和Material UI上传组件向API发送图像/文件时遇到问题

  •  0
  • Stinny  · 技术社区  · 4 年前

    我使用MaterialUI中的上传组件创建了一个图像上传组件。我过去只使用html文件输入就可以做到这一点,所以我很困惑。这些文件被选择得很好,并将它们置于组件状态。当我将它们附加到表单数据并发送到服务器(node&expressjs)时,我一直从req.files中获得一个空数组。我在服务器端使用multer来解析文件。

    以下是UI组件:

    const StepFive = ({
      handlePrevStep,
      setListingImages,
      listingImages,
      createdListing,
    }) => {
      const created = useSelector((state) => state.listings.created);
      const [fileList, setFileList] = React.useState([]);
      const dispatch = useDispatch();
    
      React.useEffect(() => {
        setListingImages(fileList);
        console.log(fileList);
      }, [fileList]);
    
      const onChange = ({ fileList: newFileList }) => {
        setFileList(newFileList);
      };
    
      const handleLisitingImages = (e) => {
        e.preventDefault();
    
        const data = new FormData();
    
        //check if image(s) have been selected yet
        //and append the images to form data
        if (fileList) {
          for (let i = 0; i < fileList.length; i++) {
            data.append('listingImage', fileList[i]);
          }
        }
    
        console.log(data.getAll('listingImage'));
    
        uploadImagesToListing(createdListing._id, data)(dispatch);
      };
    
      const onPreview = async (file) => {
        let src = file.url;
        if (!src) {
          src = await new Promise((resolve) => {
            const reader = new FileReader();
            reader.readAsDataURL(file.originFileObj);
            reader.onload = () => resolve(reader.result);
          });
        }
        const image = new Image();
        image.src = src;
        const imgWindow = window.open(src);
        imgWindow.document.write(image.outerHTML);
      };
    
      // const prevStep = (e) => {
      //   e.preventDefault();
      //   handlePrevStep();
      // };
    
      // if (!created) return <Spinner />;
    
      return (
        <Con>
          <Wrap>
            <Header>
              Step <b>5|5</b>
            </Header>
            <SubHeader>Pictures</SubHeader>
            <SubInfo>
              This is the most important part of creating a listing and attratcing
              guests. Really spend time on taking some good quality pictures of your
              place
            </SubInfo>
            <UploadForm enctype='multipart/form-data'>
              <ImgCrop rotate>
                <Upload
                  listType='picture-card'
                  fileList={fileList}
                  onChange={onChange}
                  onPreview={onPreview}
                  name='image'
                >
                  {fileList.length < 15 && '+ Upload'}
                </Upload>
              </ImgCrop>
            </UploadForm>
            <BtnCon>
              <Btn onClick={prevStep}>Prev</Btn>
              <Btn onClick={handleLisitingImages}>Finish</Btn>
            </BtnCon>
          </Wrap>
        </Con>
      );
    };
    

    这里是uploadImagesToListing函数:

    export const uploadImagesToListing = (listingId, images) => async (dispatch) => {
      await axiosInstance
        .post(`/listings/imageupload/${listingId}`, images, {
          headers: { 'Content-Type': `multipart/form-data;` },
        })
        .then((res) => {
          dispatch({
            type: uploadedImages,
          });
        })
        .catch((err) => {
          console.log(err);
        });
    };
    

    现在服务器上有一条带multer的路线:

    const storage = multer.memoryStorage();
    
    //allows routes to get files
    const multipleUpload = multer({ storage: storage }).array('listingImage');
    
    router.post(
      '/imageupload/:listingId',
      verifyToken,
      multipleUpload,
      listings.imageUpload
    );
    

    在路由处理程序中,我所做的只是尝试console.log(req.files)并不断获得一个空数组。

    解决了的 当从输入访问每个文件对象时,我需要添加fileList[I].originalfileObject,而不仅仅是fileList[I]

    0 回复  |  直到 4 年前
        1
  •  0
  •   Mohsin Baig    4 年前

    你能把斧头换成这样吗

    export const uploadImagesToListing = (listingId, images) => async (   dispatch ) => {   await axiosInstance
        .post(`/listings/imageupload/${listingId}`, images)
        .then((res) => {
          dispatch({
            type: uploadedImages,
          });
        })
        .catch((err) => {
          console.log(err);
        }); };