如何获取我以输入文件形式选择的文件的路径,以便我可以在服务器端使用 cloudinary 上传
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 发出以下请求,但它说图像路径不正确,这是有道理的,但我为所选图片拥有的对象不显示图像路径。
那么如何获得 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 钩子形式,这里是上下文的完整代码
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>
);
};
根据documentation, you can't just upload file. You will have to either save it somewhere first (for example locally on disk), or 。
有趣的是,文档的其他部分建议您发送 array buffer,但我不确定它是否在 Node
中可用
我发布这个答案只是为了让其他人受益,我最终选择了数组缓冲区路线。
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);
}
}
我能够获取图片对象下文件的文件名,如下图所示
我向 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 钩子形式,这里是上下文的完整代码
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>
);
};
根据documentation, you can't just upload file. You will have to either save it somewhere first (for example locally on disk), or
有趣的是,文档的其他部分建议您发送 array buffer,但我不确定它是否在 Node
中可用我发布这个答案只是为了让其他人受益,我最终选择了数组缓冲区路线。
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);
}
}