React 和 Node 应用程序未将图像上传到 Cloudinary,404 错误没有解释
Posted
技术标签:
【中文标题】React 和 Node 应用程序未将图像上传到 Cloudinary,404 错误没有解释【英文标题】:React and Node application not uploading Images to Cloudinary, 404 error with no explanation 【发布时间】:2021-03-23 09:37:14 【问题描述】:我正在尝试将图像上传到 cloudinary。我正在使用这个资源作为我的教程...
我能够在我的屏幕上呈现图像的预览,并在控制台记录 base64 编码的 url,它可以正常工作。选择我的图像后,我点击上传,我的 POST 请求出现 404 错误,但没有关于它发生原因的信息。我的开发控制台的网络标签下没有BAD REQUEST。我的 Cloudinary 从未渲染过任何图像。
开始,这是我的 index.js 代码
const connectDB = require('./startup/db');
const express = require('express');
const app = express();
const users = require('./routes/users');
const kittys = require('./routes/kittys');
const friends = require('./routes/friends');
const image = require('./routes/image');
const auth = require('./routes/auth')
const cors = require("cors");
const bodyParser = require('body-parser');
const path = require('path');
const logger = require('morgan');
const cookieParser = require('cookie-parser');
const cloudinary = require('./utils/cloudinary');
// const createError = require('http-errors');
connectDB();
app.use(cors());
app.use(express.json());
app.use('/api/users', users);
app.use('/api/kittys', kittys);
app.use('/api/auth', auth);
app.use('/api/friends', friends);
app.use('api/upload', image)
app.use((req, res, next) =>
res.setHeader('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
res.header('Access-Control-Allow-Credentials', true);
res.header('Access-Control-Allow-Methods', '*'); // enables all the methods to take place
return next();
);
app.use(logger('dev'));
app.use('/uploads', express.static('uploads'));
app.use(bodyParser.json(limit: '50mb'));
app.use(bodyParser.urlencoded(limit: '50mb', extended: true));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.get('/*',(req,res)=>
res.sendfile(path.join(__dirname='/public'));
)
const port = process.env.PORT || 5000;
app.listen(port, () =>
console.log(`Server started on port: $port`);
)
这是我的 image.jsx(component) 代码
import React, useState from 'react';
import Alert from './Alert.js'
export default function Upload()
const [fileInputState, setFileInputState] = useState('');
const [previewSource, setPreviewSource] = useState('');
const [selectedFile, setSelectedFile] = useState();
const [successMsg, setSuccessMsg] = useState('');
const [errMsg, setErrMsg] = useState('');
const handleFileInputChange = (e) =>
const file = e.target.files[0];
previewFile(file);
setSelectedFile(file);
setFileInputState(e.target.value);
;
const previewFile = (file) =>
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onloadend = () =>
setPreviewSource(reader.result);
;
;
const handleSubmitFile = (e) =>
e.preventDefault();
if (!selectedFile) return;
const reader = new FileReader();
reader.readAsDataURL(selectedFile);
reader.onloadend = () =>
uploadImage(reader.result);
;
reader.onerror = () =>
console.error('AHHHHHHHH!!');
setErrMsg('something went wrong!');
;
;
const uploadImage = async (base64EncodedImage) =>
console.log(base64EncodedImage)
try
await fetch('image/upload',
method: 'POST',
body: JSON.stringify( data: base64EncodedImage ),
headers: 'Content-Type': 'application/json' ,
);
setFileInputState('');
setPreviewSource('');
setSuccessMsg('Image uploaded successfully');
catch (err)
console.error(err);
setErrMsg('Something went wrong!');
;
return (
<div>
/* <h1 className="title">Upload an Image</h1> */
<Alert msg=errMsg type="danger" />
<Alert msg=successMsg type="success" />
<form onSubmit=handleSubmitFile className="form">
<input
id="fileInput"
type="file"
name="image"
onChange=handleFileInputChange
value=fileInputState
className="form-input"
/>
<button className="btn" type="submit">
Submit
</button>
</form>
previewSource && (
<img
src=previewSource
style= height: '300px'
/>
)
</div>
);
这是我的 image.js 路线:
const express = require('express');
const router = express.Router();
const cloudinary = require('../utils/cloudinary');
router.get('/api/images', async (req, res) =>
const resources = await cloudinary.search
.expression('folder:dev_setups')
.sort_by('public_id', 'desc')
.max_results(30)
.execute();
const publicIds = resources.map((file) => file.public_id);
res.send(publicIds);
);
router.post('api/upload', async (req, res) =>
try
const fileStr = req.body.data;
const uploadResponse = await cloudinary.uploader.upload(fileStr,
upload_preset: 'dev_setups',
);
console.log(uploadResponse);
res.json( msg: 'yaya' );
catch (err)
console.error(err);
res.status(500).json( err: 'Something went wrong' );
);
module.exports = router;
这是我的 Cloudinary 文件信息:
require('dotenv').config();
const 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,
);
module.exports = cloudinary ;
这是我的 App.js 文件:
import React, useState from 'react';
import Navbar, Nav, NavDropdown, Form, FormControl from 'react-bootstrap';
import Button from '@material-ui/core/Button';
import 'bootstrap/dist/css/bootstrap.min.css';
import Route, Router, useHistory from "react-router-dom";
import useCookies from 'react-cookie';
import './App.css';
import LandingPage from './components/profile/LandingPage';
import ProfilePage from './components/profile/ProfilePage';
import Homepage from './components/profile/Homepage';
import AddCat from './components/cats/AddCat';
import ProtectedRoute from './components/profile/ProtectedRoute';
import DisplayCats from './components/cats/DisplayCats';
import MyMap from './components/map/MapContainer';
import MyImage from './components/image';
// import AddFriend from './components/AddFriend' const url =
// 'https://api.cloudinary.com/v1_1/djcngbd59/image/upload'; const preset =
// 'atmhk5x9'
const App = () =>
const cookieName = 'straytracker';
const [cookies,
setCookie,
removeCookie] = useCookies([cookieName]);
const history = useHistory();
let userInfo = false;
function isEmpty(obj)
return Object
.keys(obj)
.length === 0;
if (!isEmpty(cookies))
try
// jwtDecode just grabs the token. It does not validate the token. userInfo will
// hold the user info in an object. If no jwt found, userInfo will hold the
// false value.
userInfo = cookies.straytracker;
catch
//if token is not found, send user to landing page.
history.push("/");
console.log(cookies)
console.log(userInfo, 'userinfo check')
const [user,
setUser] = useState(userInfo);
const handleLogin = e =>
e.preventDefault();
try
userInfo = cookies.straytracker;
setUser(userInfo);
history.push("/home");
window
.location
.reload(false);
alert('You have successfully logged in')
catch
alert('No token found')
history.push("/");
const handleLogout = e =>
e.preventDefault();
setUser(false);
window
.location
.reload(false);
removeCookie(cookieName, path: '/');
const setCookieApp = (jwt) =>
// let d = new Date();
setCookie(cookieName, jwt)
;
return (
<div className="App">
<header className="App-header">
<Navbar bg="light" expand="lg">
<Navbar.Brand href="/home">Stray Tracker</Navbar.Brand>
<Navbar.Toggle aria-controls="basic-navbar-nav"/>
<Navbar.Collapse id="basic-navbar-nav">
<Nav className="mr-auto">
<Nav.Link href="/home">Home</Nav.Link>
<Nav.Link href="/map">View Map</Nav.Link>
<Nav.Link href="/report">Add Cat</Nav.Link>
<Nav.Link href="/profile">Profile</Nav.Link>
<Nav.Link href="/upload">Upload Image</Nav.Link>
<NavDropdown title="More" id="basic-nav-dropdown">
<NavDropdown.Item href="/AddFriend">Add Friend</NavDropdown.Item>
/* <NavDropdown.Item href="#action/3.3">Something</NavDropdown.Item> */
<NavDropdown.Divider/> /* <NavDropdown.Item href="#action/3.4">Separated link</NavDropdown.Item> */
</NavDropdown>
</Nav>
<Button color="secondary" onClick=handleLogout>
Logout
</Button>
<Form inline>
<FormControl type="text" placeholder="Search" className="mr-sm-2"/>
<Button variant="outlined">Search</Button>
</Form>
</Navbar.Collapse>
</Navbar>
</header>
<Router history=history>
/* <ProtectedRoute exact path='/home' user=userInfo ? user:null component=Homepage handleLogout=handleLogout/> */
<Route
exact
path='/'
handleLogin=handleLogin
render=props => <LandingPage...props
user=user
handleLogin=handleLogin
setCookieApp=setCookieApp/>/>
<ProtectedRoute
exact
path='/home'
user=user
component=Homepage
handleLogout=handleLogout/>
<ProtectedRoute
exact
path='/profile'
user=user
component=ProfilePage
handleLogout=handleLogout/>
<ProtectedRoute
exact
path='/report'
user=user
component=AddCat
handleLogout=handleLogout/> /* <Route
exact
path='/map'
user=user
component=MapContainer
handleLogout=handleLogout/> */
<ProtectedRoute
exact
path='/cats'
render=props => <DisplayCats ...props user=user/>/>
<ProtectedRoute
exact
path='/upload'
user=user
component=MyImage
handleLogout=handleLogout/>
<Route exact path='/map' render=props => <MyMap ...props user=user/>/> /* <ProtectedRoute exact path='/AddFriend' user=user component=AddFriend /> */
</Router>
</div>
);
export default App
这是我的Server package.json
"name": "server",
"version": "1.0.0",
"description": "",
"main": "index.js",
"proxy": "http://localhost:3001",
"scripts":
"start": "nodemon index2.js",
"test": "echo \"Error: no test specified\" && exit 1"
,
"author": "",
"license": "ISC",
"dependencies":
"bcrypt": "^5.0.0",
"body-parser": "^1.19.0",
"cloudinary": "^1.23.0",
"config": "^3.3.2",
"cookie-parser": "^1.4.5",
"cors": "^2.8.5",
"debug": "^4.3.1",
"dotenv": "^8.2.0",
"express": "^4.17.1",
"http-errors": "^1.8.0",
"jade": "^1.11.0",
"joi": "^17.2.1",
"jsonwebtoken": "^8.5.1",
"mongoose": "^5.10.15",
"morgan": "^1.10.0",
"multer": "^1.4.2",
"nodemon": "^2.0.6",
"uuid": "^8.3.1"
【问题讨论】:
【参考方案1】:查看您共享的代码,我看到您为api/upload
定义了一个POST 路由,但是uploadImage
调用将请求发送到image/upload
,这不是一个定义的路由。您能否将uploadImage
中的端点从image/upload
更新为api/upload
并再次测试上传。
【讨论】:
以上是关于React 和 Node 应用程序未将图像上传到 Cloudinary,404 错误没有解释的主要内容,如果未能解决你的问题,请参考以下文章
将图像文件从 React 前端上传到 Node/Express/Mongoose/MongoDB 后端(不工作)
如何在上传后立即接收 Cloudinary 图像 URL(React JS 和 Node Js)?
从 Postgres 返回图像 url 到前端 - Node / React
node.js / react 使用 graphql createReadStream 上传文件不是函数
React-native node.js 显示错误:多部分:使用 react-native-image-picker 上传图像时未找到边界