【问题标题】:How to get the path of the file I selected in a form of input file so I can upload with cloudinary the server side如何以输入文件的形式获取我选择的文件的路径,以便我可以使用 cloudinary 上传服务器端
【发布时间】:2021-06-09 22:51:14
【问题描述】:

我能够得到图片对象下的文件的文件名,如下图

我使用以下内容向 cloudinary 发出请求,但它说图像路径不正确,这是有道理的,但是我为所选图片拥有的对象没有显示图像路径。

那么我如何获得 cloudinary 的正确路径。

var cloudinary = require("cloudinary").v2;

cloudinary.config({
  cloud_name: process.env.CLOUDINARY_NAME,
  api_key: process.env.CLOUDINARY_API_KEY,
  api_secret: process.env.CLOUDINARY_API_SECRET,
});

export default async function signup(req, res) {
  console.log(req.body);
  const body = req.body;

  cloudinary.uploader.upload(
    `${body}`,
    function (error, result) {
      console.log(result, error);
    }
  );

  try {
    const result = req.body;
    res.status(200).send(result);
  } catch (error) {
    console.error(error);
    res.status(error.requestResult.statusCode).send(error.message);
  }
}

这是我要发送到 api 的内容

 const res = await fetch("../api/image", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify(data.picture[0].name),
    });

    console.log(res);

我正在使用 react hook 表单,这里是上下文的完整代码

import { useForm, Controller } from "react-hook-form";
import Layout from "../components/Layout";
import ReactDatePicker from "react-datepicker";
import "react-datepicker/dist/react-datepicker.css";
import { gql, useMutation } from "@apollo/client";
import useSWR from "swr";
import { useRouter } from "next/router";

const CREATE_DECOR_ENTRY = gql`
  mutation CreateDecorEntry(
    $ownerID: ID!
    $description: String!
    $pieces: Int!
    $purchaser: String!
    $alterations: Boolean!
    $cost: Int!
    $purchaseDate: Date!
    $category: String!
  ) {
    createDecor(
      data: {
        description: $description
        pieces: $pieces
        purchaser: $purchaser
        alterations: $alterations
        cost: $cost
        purchaseDate: $purchaseDate
        category: $category
        owner: { connect: $ownerID }
      }
    ) {
      description
    }
  }
`;

const fetcher = (url) => fetch(url).then((r) => r.json());
const fetchWithImage = (url, image) =>
  fetch(`${url}?image=${image}`).then((r) => r.json());

export default function Decor() {
  const { data: user, error: userError } = useSWR("/api/user", fetcher);

  const { data: cookieData, error: cookieError } = useSWR(
    "/api/cookie",
    fetcher
  );

  var cookieBearer = `Bearer ${cookieData}`;

  return (
    <Layout>
      <h1>Enter your Decor Data</h1>

      {user && cookieBearer && <Form user={user} cookieBearer={cookieBearer} />}
    </Layout>
  );
}

const Form = ({ cookieBearer, user }) => {
  const Router = useRouter();

  const [
    createDecorEntry,
    { data: createDecorEntryData, loading: saving },
  ] = useMutation(CREATE_DECOR_ENTRY, {
    context: {
      headers: {
        authorization: cookieBearer,
      },
    },
  });

  const { register, handleSubmit, errors, control } = useForm();
  const onSubmit = async (data) => {
    console.log(data);

    let yourDate = data.purchaseDate;

    const offset = yourDate.getTimezoneOffset();
    yourDate = new Date(yourDate.getTime() - offset * 60 * 1000);
    const date = yourDate.toISOString().split("T")[0];

    console.log(date);

    const dataMassage = {
      ...data,
      pieces: parseInt(data.pieces),
      cost: parseInt(data.cost),
      purchaseDate: date,
    };

    console.log(dataMassage);

    const res = await fetch("../api/image", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify(data.picture[0].name),
    });

    console.log(res);

    // const res = await createDecorEntry({
    //   variables: {
    //     ownerID: user.id,
    //     ...dataMassage,
    //   },
    // }).catch(console.error);

    // Router.push(`/decor/data`);
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <div>
        <h2>Image</h2>
        <input ref={register} type="file" name="picture" />
      </div>
      <div>
        <h2>Description</h2>
        <input
          type="text"
          placeholder="Description"
          name="description"
          ref={register({ required: true })}
        />
      </div>
      <div>
        <h2>Number of Pieces</h2>
        <input
          type="number"
          placeholder="Number of Pieces"
          name="pieces"
          ref={register({ required: true })}
        />
      </div>
      <div>
        <h2>Purchaser</h2>
        <input
          type="text"
          placeholder="Purchaser"
          name="purchaser"
          ref={register({ required: true })}
        />
      </div>
      <div>
        <h2>Alternations Needed</h2>
        <input
          type="checkbox"
          placeholder="Alternations Needed"
          name="alterations"
          ref={register({ required: true })}
        />
      </div>
      <div>
        <h2>Cost</h2>
        <input
          type="number"
          placeholder="Cost"
          name="cost"
          ref={register({ required: true })}
        />
      </div>
      <div>
        <h2>Purchase Date</h2>
        <Controller
          name="purchaseDate"
          control={control}
          render={({ onChange, value }) => (
            <ReactDatePicker selected={value} onChange={onChange} />
          )}
        />
      </div>
      <div>
        <h2>Category</h2>
        <select name="category" ref={register}>
          <option value="Curation">Curation</option>
          <option value=" Good"> Good</option>
        </select>
      </div>

      <div>
        <input type="submit" />
      </div>
    </form>
  );
};

【问题讨论】:

    标签: javascript node.js reactjs forms cloudinary


    【解决方案1】:

    根据documentation,你不能只上传文件。您必须先将其保存在某个地方(例如本地磁盘上),或者convert it into base64

    有趣的是,文档的其他部分建议您发送array buffer,但我不确定它是否在 Node 中可用

    【讨论】:

    • 哦,所以我将它保存在磁盘上并使用该路径,或者如果我有 base64,我应该将什么传递给 cloudinary 一个长字符串而不是文件路径
    • 所以在点击浏览并选择它之后需要将其转换为baseString,我需要在那时运行服务器端函数来执行此操作。当它与 baseSring 一起返回时,react hook 表单会选择它或其他东西。由于它已注册到该输入
    • 您必须先将 base64 转换为 data-uri,但是是的 - 您要么传递本地文件路径,要么传递 base64 data-uri。我会使用本地路径 - 保存临时文件,上传到 cloudinary,删除临时文件。
    • 好的,我在这里进行了一些谷歌搜索,但是我什至从哪里开始保存临时文件,我会首先从文件输入中侦听 onChange 事件,然后不确定。我会继续寻找,但如果你知道方向会有很大帮助
    • 那么,你在 nodejs 中获取你的文件,对吧?使用fs 将此文件写入磁盘。将文件保存在磁盘上后,将其路径传递给 cloundinary uploader。上传完成后 - delete 磁盘中的文件。
    【解决方案2】:

    我发布这个答案只是为了让其他人受益,我最终选择了数组缓冲区路线。

    import formidable from "formidable";
    const cloudinary = require("cloudinary").v2;
    const fs = require("fs");
    const path = require("path");
    let streamifier = require('streamifier');
    
    cloudinary.config({
      cloud_name: process.env.CLOUDINARY_NAME,
      api_key: process.env.CLOUDINARY_API_KEY,
      api_secret: process.env.CLOUDINARY_API_SECRET,
    });
    
    // first we need to disable the default body parser
    export const config = {
      api: {
        bodyParser: false,
      },
    };
    
    export default async function image(req, res) {
      
    
      try {
    
        const form = new formidable.IncomingForm();
      form.uploadDir = "./";
      form.keepExtensions = true;
      form.parse(req, (err, fields, files) => {
        console.log(JSON.stringify(files));
    
        console.log(files.image.path);
    
        var oldPath = files.image.path;
        var rawData = fs.readFileSync(oldPath);
    
        console.log(rawData);
    
        let cld_upload_stream = cloudinary.uploader.upload_stream(
          {
            folder: "sick-fits"
          },
          function(error, result) {
              console.log(error, result);
              res.status(200).send({ result });
          }
      );
    
      streamifier.createReadStream(rawData).pipe(cld_upload_stream);
    
      });
    
      } catch (error) {
        console.error(error);
        res.status(error.requestResult.statusCode).send(error.message);
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-09-23
      • 1970-01-01
      • 1970-01-01
      • 2019-06-15
      • 2019-11-15
      • 2016-03-25
      • 2020-10-08
      • 2013-12-16
      相关资源
      最近更新 更多