我正在使用 React Native 和 Expo 工具链开发一个简单的社交媒体应用程序。该应用程序的主要功能是允许用户上传视频并与他人分享。在“浏览”屏幕上,用户应该能够查看上传的视频。这些视频是从 MongoDB Atlas 数据库检索的,预计将显示在应用程序中。但是,当我加载应用程序时,我被困在加载图标中,并且最终超时。
以下是我的设置的一些详细信息:
视频上传和检索功能由 Express.js 后端服务器处理。 我使用 Multer 中间件来处理 multipart/form-data,并使用 multer-gridfs-storage 引擎使用 GridFS 规范将上传的文件直接存储到 MongoDB。 我能够从手机成功上传视频,并且它们在 MongoDB 数据库中显示为新集合(在“test”数据库内,名为“uploads.files.chunks”和“uploads.files.files”的集合中)。 我可以从我的服务器加载静态文本(“Hello World!”消息),但视频检索不起作用。
我尝试了多种方法来诊断问题,包括:
验证我的服务器正在运行并连接到 MongoDB 通过放置控制台日志确保我的“/api/videos”路线被命中 检查数据库以查看文件是否存在(确实存在) 在浏览器开发者工具中检查网络请求(没有出现)
下面是我的 Express.js 服务器的相关代码:
const express = require('express');
const mongoose = require('mongoose');
const multer = require('multer');
const { GridFsStorage } = require('multer-gridfs-storage');
const Grid = require('gridfs-stream');
const cors = require('cors');
require('dotenv').config();
// Create Express server
const app = express();
// Enable CORS
app.use(cors());
// Database connection
const conn = mongoose.createConnection(process.env.MONGODB_URI, {
useNewUrlParser: true,
useUnifiedTopology: true,
});
conn.on('connected', () => {
console.log('Connected to MongoDB');
});
conn.on('error', (err) => {
console.error('Failed to connect to MongoDB', err);
});
let gfs;
conn.once('open', () => {
// Initialize GridFS
gfs = Grid(conn.db, mongoose.mongo);
gfs.collection('uploads.files');
// Add this test query
conn.db.collection('uploads.files').find().limit(1).toArray((err, docs) => {
console.log('Test Query executed');
if (err) {
console.log('Error executing test query', err);
} else if (docs.length === 0) {
console.log('Test query returned no documents');
} else {
console.log('Test query returned document:', docs[0]);
}
});
// Start server
const port = process.env.PORT || 5000;
app.listen(port, () => {
console.log(`Server is running on port ${port}`);
});
});
// Create storage engine
const storage = new GridFsStorage({
url: process.env.MONGODB_URI,
options: { useNewUrlParser: true, useUnifiedTopology: true },
file: (req, file) => {
return new Promise((resolve, reject) => {
// Use the _id as the filename
const filename = new mongoose.Types.ObjectId();
const fileInfo = {
filename: filename,
bucketName: 'uploads.files',
};
resolve(fileInfo);
});
},
});
const upload = multer({ storage });
// Middleware
app.use(express.json());
// Routes
app.get('/', (req, res) => {
res.send('Hello World!');
});
app.post('/api/videos', upload.single('video'), (req, res) => {
console.log('Upload route hit');
console.log('req.body:', req.body);
console.log('req.file:', req.file);
// Video uploaded successfully
res.json({ message: 'Video uploaded successfully' });
});
app.get('/api/videos', (req, res) => {
console.log('Get videos route hit');
gfs.files.find().sort({ uploadDate: -1 }).toArray((err, files) => {
// Check if an error occurred during the database query
if (err) {
console.error('Error occurred during database query:', err);
return res.status(500).json({ message: 'Internal server error' });
}
// Check if files exist
if (!files || files.length === 0) {
console.log('No files exist');
return res.status(404).json({ message: 'No files exist' });
}
// Files exist
console.log('Files found:', files);
return res.json(files);
}).catch(err => console.error('Error executing query:', err)); // Add this line
});
这是我的前端 React Native 应用程序的相关代码:
import React, { useEffect, useState } from 'react';
import { View, Text, ActivityIndicator, StyleSheet } from 'react-native';
import axios from 'axios';
import VideoPlayer from '../components/VideoPlayer';
function Explore() {
const [videos, setVideos] = useState([]);
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
const fetchVideos = async () => {
try {
const response = await axios.get('http://localhost:5000/api/videos');
console.log('Response data:', response.data); // Add this line
setVideos(response.data);
setIsLoading(false);
} catch (err) {
console.log('Error:', err); // Add this line
setError(err.message);
setIsLoading(false);
}
};
fetchVideos();
}, []);
if (isLoading) {
return (
<View style={styles.loadingContainer}>
<ActivityIndicator size="large" color="#0000ff" />
</View>
);
}
if (error) {
return (
<View style={styles.errorContainer}>
<Text style={styles.errorText}>Error: {error}</Text>
</View>
);
}
return (
<View style={styles.container}>
{videos.length > 0 ? (
videos.map(video => (
<VideoPlayer key={video._id} videoId={video._id} /> // Replace _id with filename if necessary
))
) : (
<Text>No videos found.</Text>
)}
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
backgroundColor: '#ecf0f1',
},
loadingContainer: {
flex: 1,
justifyContent: 'center',
},
errorContainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
padding: 20,
},
errorText: {
color: 'red',
fontSize: 18,
textAlign: 'center',
},
});
export default Explore;
当我尝试加载“探索”屏幕时,我只在终端中看到“获取视频路由命中”,而没有其他内容。屏幕继续显示加载图标。
任何帮助将不胜感激,因为我不确定如何从这里继续。甚至 ChatGPT 也对我说“抱歉,我不明白这个”哈哈。