如何使用Node API将图片存储到共享主机服务商
实现方案
Heroku免费Dyno采用临时文件系统,每次部署、休眠重启后本地存储的文件都会被清空,因此无法直接使用multer存储文件到Dyno本地,使用你手头的共享主机作为独立存储节点是完全可行的,具体实现流程如下:
1. 配置共享主机端上传服务
你需要在共享主机上部署一个极简的上传接收服务,仅负责文件接收、存储、返回公网访问地址,支持Node.js或PHP两种实现方式:
- 核心逻辑:接收上传请求→鉴权→将文件存入共享主机的公开可访问目录→返回文件的公网访问URL
- 必须配置:确保存储的图片可以通过固定公网路径直接访问,格式示例为
https://<你的共享主机域名>/uploads/<文件名> - 鉴权配置:在请求头中增加自定义密钥校验,避免恶意上传
Node.js实现示例
const express = require('express'); const multer = require('multer'); const app = express(); // 配置存储路径为共享主机的公开可访问目录 const storage = multer.diskStorage({ destination: (req, file, cb) => cb(null, '/path/to/your/shared/host/public/uploads'), filename: (req, file, cb) => { // 生成唯一文件名避免覆盖 const uniqueName = `${Date.now()}-${Math.round(Math.random() * 1e9)}-${file.originalname}`; cb(null, uniqueName); } }); const upload = multer({ storage }); // 自定义鉴权中间件 const uploadAuth = (req, res, next) => { if (req.headers['x-upload-key'] !== 'YOUR_CUSTOM_SECRET_KEY') { return res.status(403).send('Unauthorized'); } next(); }; // 上传接口 app.post('/upload', uploadAuth, upload.single('image'), (req, res) => { const publicUrl = `https://<你的共享主机域名>/uploads/${req.file.filename}`; res.json({ url: publicUrl }); }); app.listen(3000, () => console.log('Upload service running'));
PHP实现示例(适用于仅支持PHP的共享主机)
// upload.php <?php header('Content-Type: application/json'); // 鉴权 if ($_SERVER['HTTP_X_UPLOAD_KEY'] !== 'YOUR_CUSTOM_SECRET_KEY') { http_response_code(403); echo json_encode(['error' => 'Unauthorized']); exit; } // 生成唯一文件名 $fileName = time() . '-' . rand(100000, 999999) . '-' . $_FILES['image']['name']; $savePath = '/path/to/your/shared/host/public/uploads/' . $fileName; // 存储文件 if (move_uploaded_file($_FILES['image']['tmp_name'], $savePath)) { $publicUrl = 'https://<你的共享主机域名>/uploads/' . $fileName; echo json_encode(['url' => $publicUrl]); } else { http_response_code(500); echo json_encode(['error' => 'Upload failed']); } ?>
2. 修改Heroku端Node.js API逻辑
将原multer本地存储改为内存存储,收到前端上传请求后直接转发到共享主机的上传接口,拿到返回的URL后写入Postgres数据库即可:
const express = require('express'); const multer = require('multer'); const axios = require('axios'); const FormData = require('form-data'); const { Pool } = require('pg'); const app = express(); const db = new Pool({ /* 你的Postgres连接配置 */ }); // 配置multer使用内存存储,不写入本地磁盘 const storage = multer.memoryStorage(); const upload = multer({ storage }); // 前端调用的上传接口 app.post('/api/upload', upload.single('image'), async (req, res) => { try { // 构造表单数据转发到共享主机 const form = new FormData(); form.append('image', req.file.buffer, req.file.originalname); // 请求共享主机上传接口 const uploadRes = await axios.post('https://<你的共享主机域名>/upload', form, { headers: { ...form.getHeaders(), 'x-upload-key': 'YOUR_CUSTOM_SECRET_KEY' } }); const imageUrl = uploadRes.data.url; // 将图片URL写入Postgres数据库,可根据业务逻辑关联对应记录 await db.query( 'INSERT INTO images (url, relate_id, created_at) VALUES ($1, $2, NOW())', [imageUrl, req.body.relate_id] ); res.json({ success: true, url: imageUrl }); } catch (err) { res.status(500).json({ success: false, error: 'Upload failed' }); } }); app.listen(process.env.PORT || 3000);
3. 额外优化建议
- 给共享主机的
uploads目录配置防盗链规则,仅允许你的前端域名和Heroku域名访问,避免带宽被恶意消耗 - 配置图片缓存规则,设置较长的
Cache-Control有效期,减少重复请求的带宽占用 - 可增加文件格式、大小校验,避免非法文件上传
- 定期备份共享主机上的图片文件,避免数据丢失
内容的提问来源于stack exchange,提问作者Sarthak
相关产品推荐
相关产品推荐

