如何在上传后立即接收 Cloudinary 图片 URL(React JS 和 Node Js)?
How to receive Cloudinary image URL immediately upon upload (React JS and Node Js)?
我可以成功上传图片到Cloudinary。但我的问题是如何在上传后立即将成功上传的图片的 Cloudinary url 发回给我?
我知道它作为 const uploadedResponse = await cloudinary.uploader.upload(fileStr, {upload_preset: 'dev_setups'})
的一部分发回,但这是在后端(见下面的代码 #2),我想在前端接收 URL(见代码#1 下面)所以我可以将它设置为 React 状态。实现此目标的最佳方法是什么?
如果您需要更多详细信息,请告诉我。
代码#1:下面是我上传图片到Cloudinary的代码(Cloudinary具体代码在下面注释以供参考/* Cloudinary upload */
)
import React, { useState } from 'react'
import { Card, Button, CardContent } from '@material-ui/core';
import { post, makePostAction } from '../actions';
import { useSelector, useDispatch } from 'react-redux';
export default function MakePost() {
const [title, setTitle] = useState("")
const dispatch = useDispatch();
const usernameHandle = useSelector(state => state.username)
const [fileInputState, setFileInputState] = useState('') /* new */
const [previewSource, setPreviewSource] = useState('') /* new */
const [selectedFile, setSelectedFile] = useState('') /* new */
const onInputChange = (event) => {
setTitle(event.target.value);
}
const handleSubmit = (evt) => {
evt.preventDefault();
if (!title) return
dispatch(makePostAction({
title,
comment: false,
comments_text: "",
handle: usernameHandle,
post_date: new Date().getTime()
}))
setTitle("")
}
/* Cloudinary upload */
const handleFileInputChange = (e) => {
const file = e.target.files[0]
previewFile(file)
}
const previewFile = (file) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onloadend = () => {
setPreviewSource(reader.result)
}
}
const handleSubmitFile = (e) => {
e.preventDefault();
if(!previewSource) return;
uploadImage(previewSource)
}
const uploadImage = async (base64EncodedImage) => {
console.log(base64EncodedImage)
try {
await fetch('/api/upload', {
method: 'POST',
body: JSON.stringify({data: base64EncodedImage}),
headers: {'Content-type': 'application/json'}
})
} catch (error) {
console.error(error)
}
}
/* Cloudinary upload */
return (
<div>
<Card>
<CardContent>
<form onSubmit={handleSubmit}>
<input type="text" value={title} onChange={onInputChange} />
</form>
{/* new */}
<form onSubmit={handleSubmitFile} className="form">
<input type="file" name="image" onChange={handleFileInputChange} value={fileInputState} className="form-input" />
<button className="btn" type="submit">Submit</button>
</form>
{/* new */}
{previewSource && (
<img
src={previewSource}
alt="chosen"
style={{height: '300px'}}
/>
)}
</CardContent>
</Card>
</div>
)
}
代码#2:这是我的server.js
const express = require('express');
const app = express();
const {cloudinary} = require('./utils/cloudinary');
app.use(express.json({limit: '50mb'}));
app.use(express.urlencoded({limit: '50mb', extended: true}))
app.get('/api/images', async (req, res) => {
const {resources} = await cloudinary.search.expression('folder:dev_setups')
.sort_by('public_id', 'desc')
.max_results(1)
.execute()
const publicIds = resources.map(file => file.secure_url)
res.send(publicIds)
})
app.post('/api/upload', async (req, res) => {
try {
const fileStr = req.body.data;
const uploadedResponse = await cloudinary.uploader.upload(fileStr, {upload_preset: 'dev_setups'})
res.json({msg: "Success"})
} catch (error){
console.error(error)
res.status(500).json({err: 'Something went wrong'})
}
})
const port = process.env.PORT || 3001
app.listen(port, () => {
console.log(`listening on port ${port}`)
});
Cloudinary 上传响应对象包含一个 secure_url
属性,您可以将其发送回前端。查看代码 #2,您似乎正在发送一条“成功”消息 (res.json({msg: "Success"})
)。听起来您想将该行更改为 -
res.json({url: uploadedResponse.secure_url})
在您的前端(代码 #1),我会考虑从 async/await
切换到 .then
机制,因为您不希望整个应用等待响应 -
const uploadImage = (base64EncodedImage) => {
console.log(base64EncodedImage);
fetch('/api/upload', {
method: 'POST',
body: JSON.stringify({data: base64EncodedImage}),
headers: {'Content-type': 'application/json'}
})
.then(doWhateverYouWant)
.catch((error) => console.error(error))
}
const doWhateverYouWant = async (res) => {
// you can use res.url
}
我可以成功上传图片到Cloudinary。但我的问题是如何在上传后立即将成功上传的图片的 Cloudinary url 发回给我?
我知道它作为 const uploadedResponse = await cloudinary.uploader.upload(fileStr, {upload_preset: 'dev_setups'})
的一部分发回,但这是在后端(见下面的代码 #2),我想在前端接收 URL(见代码#1 下面)所以我可以将它设置为 React 状态。实现此目标的最佳方法是什么?
如果您需要更多详细信息,请告诉我。
代码#1:下面是我上传图片到Cloudinary的代码(Cloudinary具体代码在下面注释以供参考/* Cloudinary upload */
)
import React, { useState } from 'react'
import { Card, Button, CardContent } from '@material-ui/core';
import { post, makePostAction } from '../actions';
import { useSelector, useDispatch } from 'react-redux';
export default function MakePost() {
const [title, setTitle] = useState("")
const dispatch = useDispatch();
const usernameHandle = useSelector(state => state.username)
const [fileInputState, setFileInputState] = useState('') /* new */
const [previewSource, setPreviewSource] = useState('') /* new */
const [selectedFile, setSelectedFile] = useState('') /* new */
const onInputChange = (event) => {
setTitle(event.target.value);
}
const handleSubmit = (evt) => {
evt.preventDefault();
if (!title) return
dispatch(makePostAction({
title,
comment: false,
comments_text: "",
handle: usernameHandle,
post_date: new Date().getTime()
}))
setTitle("")
}
/* Cloudinary upload */
const handleFileInputChange = (e) => {
const file = e.target.files[0]
previewFile(file)
}
const previewFile = (file) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onloadend = () => {
setPreviewSource(reader.result)
}
}
const handleSubmitFile = (e) => {
e.preventDefault();
if(!previewSource) return;
uploadImage(previewSource)
}
const uploadImage = async (base64EncodedImage) => {
console.log(base64EncodedImage)
try {
await fetch('/api/upload', {
method: 'POST',
body: JSON.stringify({data: base64EncodedImage}),
headers: {'Content-type': 'application/json'}
})
} catch (error) {
console.error(error)
}
}
/* Cloudinary upload */
return (
<div>
<Card>
<CardContent>
<form onSubmit={handleSubmit}>
<input type="text" value={title} onChange={onInputChange} />
</form>
{/* new */}
<form onSubmit={handleSubmitFile} className="form">
<input type="file" name="image" onChange={handleFileInputChange} value={fileInputState} className="form-input" />
<button className="btn" type="submit">Submit</button>
</form>
{/* new */}
{previewSource && (
<img
src={previewSource}
alt="chosen"
style={{height: '300px'}}
/>
)}
</CardContent>
</Card>
</div>
)
}
代码#2:这是我的server.js
const express = require('express');
const app = express();
const {cloudinary} = require('./utils/cloudinary');
app.use(express.json({limit: '50mb'}));
app.use(express.urlencoded({limit: '50mb', extended: true}))
app.get('/api/images', async (req, res) => {
const {resources} = await cloudinary.search.expression('folder:dev_setups')
.sort_by('public_id', 'desc')
.max_results(1)
.execute()
const publicIds = resources.map(file => file.secure_url)
res.send(publicIds)
})
app.post('/api/upload', async (req, res) => {
try {
const fileStr = req.body.data;
const uploadedResponse = await cloudinary.uploader.upload(fileStr, {upload_preset: 'dev_setups'})
res.json({msg: "Success"})
} catch (error){
console.error(error)
res.status(500).json({err: 'Something went wrong'})
}
})
const port = process.env.PORT || 3001
app.listen(port, () => {
console.log(`listening on port ${port}`)
});
Cloudinary 上传响应对象包含一个 secure_url
属性,您可以将其发送回前端。查看代码 #2,您似乎正在发送一条“成功”消息 (res.json({msg: "Success"})
)。听起来您想将该行更改为 -
res.json({url: uploadedResponse.secure_url})
在您的前端(代码 #1),我会考虑从 async/await
切换到 .then
机制,因为您不希望整个应用等待响应 -
const uploadImage = (base64EncodedImage) => {
console.log(base64EncodedImage);
fetch('/api/upload', {
method: 'POST',
body: JSON.stringify({data: base64EncodedImage}),
headers: {'Content-type': 'application/json'}
})
.then(doWhateverYouWant)
.catch((error) => console.error(error))
}
const doWhateverYouWant = async (res) => {
// you can use res.url
}