【问题标题】:How to upload Image from Next JS Strapi API如何从 Next JS Strapi API 上传图片
【发布时间】:2022-06-30 20:05:39
【问题描述】:

如何将 NextJS 中的图像添加到 Strapi Media 库?我尝试从 NextJS 前端上传图像,图像将上传到我的 Strapi Media 库和我的 Cloudinary 帐户,但图像不会关联/链接到该特定帖子 这是我的代码

路径:components/ImageUpload.js

import { useState } from "react";
import { API_URL } from "../config/index";
import styles from "@/styles/FormImage.module.css";

export default function ImageUpload({ sportNewsId, imageUploaded }) {
  const [image, setImage] = useState(null);

  const handleFilechange = (e) => {
    console.log(e.target.files);
    setImage(e.target.files[0]);
  };

  const handleSubmit = async (e) => {
    e.preventDefault();
    const formData = new FormData();
    formData.append("files", image);
    formData.append("ref", "sports");
    formData.append("refid", sportNewsId);
    formData.append("field", "image");

    const res = await fetch(`${API_URL}/upload`, {
      method: "POST",
      body: formData,
    });
    if (res.ok) {
      imageUploaded();
    }
  };

  return (
    <div className={styles.form}>
      <h4>Upload Sport News Image</h4>
      <form onSubmit={handleSubmit}>
        <div className={styles.file}>
          <input type="file" onChange={handleFilechange} />
          <input type="submit" value="Upload" className="btn" />
        </div>
      </form>
    </div>
  );
}

路径:pages/news/edit/[id].js

import Link from "next/link";
import { useState } from "react";
import Image from "next/image";
import { useRouter } from "next/router";
import moment from "moment";
import { ToastContainer, toast } from "react-toastify";
import "react-toastify/dist/ReactToastify.css";
import Layout from "@/components/Layout";
import { API_URL } from "@/config/index";
import styles from "@/styles/FormEdit.module.css";
import Modal from "@/components/Modal";
import ImageUpload from "@/components/ImageUpload";

export default function EditNews({ sportNews }) {
  const [values, setValues] = useState({
    name: sportNews.name,
    detail: sportNews.detail,
    date: sportNews.date,
    time: sportNews.time,
  });
  const [previewImage, setPreviewImage] = useState(
    sportNews.image ? sportNews.image.formats.thumbnail.url : null
  );
  const [showModal, setShowModal] = useState(false);
  const router = useRouter();
  const { name, detail, date, time } = values;
  const handleSubmit = async (e) => {
    e.preventDefault();
    const emptyFieldCheck = Object.values(values).some(
      (element) => element === ""
    );
    if (emptyFieldCheck) {
      toast.error("Please fill all input field");
    }
    const response = await fetch(`${API_URL}/sports/${sportNews.id}`, {
      method: "PUT",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify(values),
    });
    if (!response.ok) {
      toast.error("something went wrong!!!");
    } else {
      const sport = await response.json();
      router.push(`/news/${sport.slug}`);
    }
  };

  const imageUploaded = async (e) => {
    const res = await fetch(`${API_URL}/sports/${sportNews.id}`);
    const data = await res.json();
    console.log("showing =>", data);
    console.log(setPreviewImage);
    setPreviewImage(data.image[0].formats.thumbnail.url);
    setShowModal(false);
  };

  const handleInputchange = (e) => {
    const { name, value } = e.target;
    setValues({ ...values, [name]: value });
  };
  return (
    <Layout title="Add New Sport News">
      <Link href="/news">Go Back</Link>
      <h2>Add Sport News</h2>
      <ToastContainer />
      <form onSubmit={handleSubmit} className={styles.form}>
        <div className={styles.grid}>
          <div>
            <label htmlFor="name">Name</label>
            <input
              name="name"
              id="name"
              type="text"
              value={name}
              onChange={handleInputchange}
            />
          </div>
          <div>
            <label htmlFor="date">Date</label>
            <input
              name="date"
              id="date"
              type="date"
              value={moment(date).format("yyyy-MM-DD")}
              onChange={handleInputchange}
            />
          </div>
          <div>
            <label htmlFor="time">Time</label>
            <input
              name="time"
              id="time"
              type="text"
              value={time}
              onChange={handleInputchange}
            />
          </div>
        </div>
        <div>
          <label htmlFor="detail">Detail</label>
          <textarea
            name="detail"
            id="detail"
            type="text"
            value={detail}
            onChange={handleInputchange}
          />
        </div>
        <input className="btn" type="submit" value="Add News" />
      </form>
      {/* {console.log(previewImage)} */}
      {previewImage ? (
        <Image src={previewImage} height={100} width={180} />
      ) : (
        <div>
          <p>No Image Available</p>
        </div>
      )}
      <div>
        <button onClick={() => setShowModal(true)} className="btn-edit">
          Update Image
        </button>
      </div>
      <Modal show={showModal} onClose={() => setShowModal(false)}>
        <ImageUpload sportNewsId={sportNews.id} imageUploaded={imageUploaded} />
      </Modal>
    </Layout>
  );
}
export async function getServerSideProps({ params: { id } }) {
  const res = await fetch(`${API_URL}/sports/${id}`);
  const sportNews = await res.json();
  return {
    props: { sportNews },
  };
}

这是它显示的错误消息。

我该如何解决这个错误,任何帮助将不胜感激 非常感谢

【问题讨论】:

    标签: next.js strapi cloudinary


    【解决方案1】:

    根据我的观察,问题出在 setPreviewImage 行上,从图像中删除 [0] 数组括号,以便在每次上传图像后访问您将从 Strapi API 获得的 Cloudinary 缩略图 URL。

    下面的函数应该可以让它工作

    const imageUploaded = async (e) => {
        const res = await fetch(`${API_URL}/sports/${sportNews.id}`);
        const data = await res.json();
        console.log("showing =>", data);
        console.log(setPreviewImage);
        setPreviewImage(data.image.formats.thumbnail.url);
        setShowModal(false);
      };
    

    【讨论】:

    • 我试了一下,但错误不断出现。我不知道它是否是我正在使用的 Strapi 版本,因为如果更改 formData.append("refid", sportNewsId) to formData.append("refId", sportNewsId) 我将从 Strapi 收到此错误 TypeError: Cannot read property 'associations' of undefined at D:\websites\fineback\node_modules\strapi-connector-bookshelf\lib\relations.js:259:46 并且图像不会上传到使用 strapi 3.6.8 的 Strapi
    【解决方案2】:

    对于 formData,您必须添加一个标题:

    'Content-Type': 'multipart/form-data'

    我一直在努力寻找这个。我直接从条目上传文件,而不是使用 /upload 路由,但它可能以相同的方式工作。这里使用 axios 作为 post 方法是一个例子:

      const form = new FormData();
    
      const postData = {
        name: 'test2',
      };
      form.append('files.image', file);
      form.append('data', JSON.stringify(postData));
      await axios
        .post(getStrapiURL('/ingredients'), form, {
          headers: {
            'Content-Type': 'multipart/form-data',
          },
        })
        .then((response) => {
          // Handle success.
          console.log('Well done!');
          console.log('Data: ', response.data);
        })
        .catch((error) => {
          // Handle error.
          console.log('An error occurred:', error.response);
        });
    

    【讨论】:

      猜你喜欢
      • 2021-11-20
      • 2022-11-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-12
      • 2022-01-11
      • 2022-10-06
      • 1970-01-01
      相关资源
      最近更新 更多