Nodejs新人请教个上传的问题

Nodejs新人请教个上传的问题

现在用的是express框架,multer中间件上传到服务器上的临时路径。 然后调用又拍的api,再从服务器上传到又拍云。 在本地开发的时候一切都很正常,但是部署应用到heroku上的时候,发现heroku 处理上传很慢,尤其是从heroku上传到又拍,大于1m的文件就会超时了。

有没有办法能直接上传到又拍云,而不经过服务器中转呢? 或者说还有其他的图片持久化方案?谢谢

2 回复

当然可以!对于你的问题,有两种主要的方法来解决:

  1. 直接上传到又拍云:通过前端直接上传文件到又拍云,避免经过服务器中转。
  2. 使用其他持久化方案:例如使用AWS S3、Google Cloud Storage等。

方法一:直接上传到又拍云

步骤:

  1. 在前端(例如使用JavaScript)使用fetchaxios等库将文件直接发送到又拍云的API。
  2. 使用又拍云提供的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>

解释

  1. 后端

    • generateUploadToken 函数负责向又拍云API请求上传token。
    • /upload-token 路由处理前端发送的请求,并返回上传token。
  2. 前端

    • 用户选择文件后,触发 uploadFile 函数。
    • 该函数首先向后端请求上传token。
    • 然后使用这个token和文件直接向又拍云上传文件。

这种方式可以有效避免服务器中转带来的延迟和超时问题。

回到顶部