Nodejs新人请教个上传的问题
Nodejs新人请教个上传的问题
现在用的是express框架,multer中间件上传到服务器上的临时路径。 然后调用又拍的api,再从服务器上传到又拍云。 在本地开发的时候一切都很正常,但是部署应用到heroku上的时候,发现heroku 处理上传很慢,尤其是从heroku上传到又拍,大于1m的文件就会超时了。
有没有办法能直接上传到又拍云,而不经过服务器中转呢? 或者说还有其他的图片持久化方案?谢谢
2 回复
当然可以!对于你的问题,有两种主要的方法来解决:
- 直接上传到又拍云:通过前端直接上传文件到又拍云,避免经过服务器中转。
- 使用其他持久化方案:例如使用AWS S3、Google Cloud Storage等。
方法一:直接上传到又拍云
步骤:
- 在前端(例如使用JavaScript)使用
fetch
或axios
等库将文件直接发送到又拍云的API。 - 使用又拍云提供的API和签名机制来生成一个上传请求。
示例代码:
前端代码(假设你已经获取了必要的凭证和配置信息):
async function uploadFile(file) {
const formData = new FormData();
formData.append('file', file);
const response = await fetch('https://your-upyun-endpoint', {
method: 'POST',
body: formData,
headers: {
Authorization: `Bearer ${yourAccessToken}`
}
});
if (response.ok) {
console.log('Upload successful!');
} else {
console.error('Upload failed:', response.statusText);
}
}
// 调用函数上传文件
document.getElementById('upload-button').addEventListener('click', () => {
const fileInput = document.getElementById('file-input');
if (fileInput.files.length > 0) {
uploadFile(fileInput.files[0]);
}
});
后端代码(用于生成签名和凭证):
const express = require('express');
const multer = require('multer');
const crypto = require('crypto');
const app = express();
app.use(express.static('public'));
app.post('/generate-signature', (req, res) => {
// 生成一个随机的签名或使用JWT等安全方式
const signature = crypto.randomBytes(16).toString('hex');
res.json({ signature });
});
app.listen(3000, () => {
console.log('Server running on port 3000');
});
方法二:使用其他持久化方案
示例代码:
使用AWS S3上传文件:
const AWS = require('aws-sdk');
AWS.config.update({
accessKeyId: 'YOUR_ACCESS_KEY_ID',
secretAccessKey: 'YOUR_SECRET_ACCESS_KEY',
region: 'us-west-2'
});
const s3 = new AWS.S3();
async function uploadToS3(file) {
const params = {
Bucket: 'your-bucket-name',
Key: 'path/to/file.jpg',
Body: file,
ContentType: 'image/jpeg'
};
try {
const data = await s3.upload(params).promise();
console.log('File uploaded successfully:', data.Location);
} catch (error) {
console.error('Error uploading file:', error);
}
}
通过这些方法,你可以避免在Heroku上遇到的上传延迟问题,并提高整体性能。希望这对你有所帮助!
当然可以。你可以考虑使用直传的方式将文件直接上传到又拍云(或任何其他对象存储服务),这样可以避免通过服务器中转,从而减少传输延迟和超时问题。
示例:使用 Multer 和 又拍云直传
首先,你需要在前端获取上传token,然后前端可以直接将文件上传到又拍云。下面是一个基本的实现思路:
后端代码(Express + Multer)
const express = require('express');
const multer = require('multer');
const crypto = require('crypto');
const axios = require('axios');
const app = express();
const upload = multer({ dest: 'uploads/' });
app.post('/upload-token', async (req, res) => {
try {
const token = await generateUploadToken(req.body.fileName);
res.json({ token });
} catch (error) {
console.error(error);
res.status(500).json({ error: 'Failed to generate token' });
}
});
async function generateUploadToken(fileName) {
// 这里需要你自己的逻辑来生成上传token
// 例如,向又拍云API请求一个token
const response = await axios.get(`https://your-upyun-api-url?file_name=${fileName}`);
return response.data.token;
}
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
前端代码(HTML + JavaScript)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>File Upload</title>
</head>
<body>
<input type="file" id="fileInput">
<button onclick="uploadFile()">Upload</button>
<script>
async function uploadFile() {
const fileInput = document.getElementById('fileInput');
const file = fileInput.files[0];
const response = await fetch('/upload-token', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ fileName: file.name })
});
const data = await response.json();
const token = data.token;
// 使用获取到的token直接上传到又拍云
const formData = new FormData();
formData.append('file', file);
formData.append('Authorization', token);
const uploadResponse = await fetch('https://your-upyun-upload-url', {
method: 'POST',
body: formData
});
if (uploadResponse.ok) {
alert('File uploaded successfully!');
} else {
alert('Failed to upload file.');
}
}
</script>
</body>
</html>
解释
-
后端:
generateUploadToken
函数负责向又拍云API请求上传token。/upload-token
路由处理前端发送的请求,并返回上传token。
-
前端:
- 用户选择文件后,触发
uploadFile
函数。 - 该函数首先向后端请求上传token。
- 然后使用这个token和文件直接向又拍云上传文件。
- 用户选择文件后,触发
这种方式可以有效避免服务器中转带来的延迟和超时问题。