Como configurar upload de arquivo PHP/Node.js no Render | Disk, variáveis de ambiente e integração S3
Render é uma plataforma em nuvem popular como alternativa ao Heroku. Como usa um modelo de processo residente (Web Service) em vez de Serverless, a arquitetura de upload de arquivo difere da Vercel e Netlify. Este artigo explora a configuração de armazenamento persistente (Disk) no Render, como alterar <code>upload_max_filesize</code> em ambientes PHP, configuração S3 usando variáveis de ambiente, e exemplos de configuração em Infrastructure as Code (IaC) com <code>render.yaml</code> (Blueprint).
O que é Render Disk (Armazenamento Persistente)
O Web Service do Render é efêmero por padrão (o sistema de arquivos é redefinido ao reimplantar). Para persistir arquivos enviados, você precisa adicionar um Disk.
| Tipo de armazenamento | Persistência | Compartilhamento entre múltiplas instâncias | Custo |
|---|---|---|---|
| Disco efêmero (padrão) | Redefinir na reimplantação | Não permitido | Gratuito |
| Render Disk (Persistente) | Persistente (retido até exclusão manual) | Não permitido (apenas 1 instância) | $0.25/GB/mês |
| AWS S3 (externo) | Persistente | Possível | Em conformidade com a precificação do S3 |
Como Render Disk não oferece suporte a scale-out (múltiplas instâncias), é recomendada a integração com S3 para uploads de arquivos em produção. O Disk é adequado para ambientes de desenvolvimento e staging ou operações com instância única.
Configuração de Disco no Render Dashboard
O Disk pode ser adicionado nas configurações do Web Service do Render Dashboard.
# render.yaml(Blueprint)での Disk 設定
services:
- type: web
name: my-app
runtime: node
buildCommand: npm install && npm run build
startCommand: npm start
disk:
name: uploads-disk
mountPath: /app/uploads # アプリ内でのマウントパス
sizeGB: 10 # 10GB のディスク
envVars:
- key: UPLOAD_DIR
value: /app/uploads
// Node.js での Disk へのファイル保存
const path = require('path');
const fs = require('fs');
const UPLOAD_DIR = process.env.UPLOAD_DIR || path.join(__dirname, 'uploads');
// アップロードディレクトリが存在しない場合は作成
if (!fs.existsSync(UPLOAD_DIR)) {
fs.mkdirSync(UPLOAD_DIR, { recursive: true });
}
// multer の設定例(Disk ストレージ)
const multer = require('multer');
const storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, UPLOAD_DIR);
},
filename: (req, file, cb) => {
const uniqueSuffix = `${Date.now()}-${Math.round(Math.random() * 1e9)}`;
const ext = path.extname(file.originalname);
cb(null, `upload-${uniqueSuffix}${ext}`);
},
});
const upload = multer({
storage,
limits: { fileSize: 50 * 1024 * 1024 }, // 50MB
fileFilter: (req, file, cb) => {
const allowedTypes = ['image/jpeg', 'image/png', 'image/webp', 'application/pdf'];
if (allowedTypes.includes(file.mimetype)) {
cb(null, true);
} else {
cb(new Error('許可されていないファイル形式です。'));
}
},
});
Configuração de upload_max_filesize no ambiente PHP
Para aplicativos PHP no Render (baseado em Docker), você pode ajustar o tamanho de upload alterando as configurações em <code>php.ini</code>. Como Render permite configurações arbitrárias no Docker, é mais flexível do que outros serviços de hospedagem.
# Dockerfile(PHP アプリ)
FROM php:8.2-fpm
# 必要な拡張をインストール
RUN docker-php-ext-install pdo pdo_mysql
# php.ini の設定をオーバーライド
RUN echo "upload_max_filesize = 100M" > /usr/local/etc/php/conf.d/uploads.ini \
&& echo "post_max_size = 110M" >> /usr/local/etc/php/conf.d/uploads.ini \
&& echo "memory_limit = 256M" >> /usr/local/etc/php/conf.d/uploads.ini \
&& echo "max_execution_time = 120" >> /usr/local/etc/php/conf.d/uploads.ini \
&& echo "max_input_time = 120" >> /usr/local/etc/php/conf.d/uploads.ini
WORKDIR /var/www/html
COPY . .
EXPOSE 9000
CMD ["php-fpm"]
# php.ini(直接配置する場合)
; ファイルアップロードの有効化
file_uploads = On
; 1ファイルあたりの上限
upload_max_filesize = 100M
; POST データ全体の上限(upload_max_filesize より大きくする)
post_max_size = 110M
; PHP スクリプトのメモリ上限
memory_limit = 256M
; スクリプトの最大実行時間(秒)
max_execution_time = 120
; ファイル入力待ちの最大時間(秒)
max_input_time = 120
; 一時ファイルのディレクトリ(Render の場合は /tmp を使用)
upload_tmp_dir = /tmp
<?php
// .htaccess が使えない場合は ini_set() で実行時に変更(共有ホスティングでは制限あり)
// Render(Docker)では Dockerfile での設定が確実
// ini_set() による実行時オーバーライド(一部の設定のみ有効)
ini_set('memory_limit', '256M');
// upload_max_filesize と post_max_size は実行時変更不可(php.ini での設定が必要)
// 設定値の確認
echo ini_get('upload_max_filesize'); // "100M"
echo ini_get('post_max_size'); // "110M"
echo ini_get('memory_limit'); // "256M"
Configuração S3 usando variáveis de ambiente
Configure as variáveis de ambiente no Render Dashboard ou em <code>render.yaml</code> para que seu aplicativo acesse o AWS S3. Use o recurso de gerenciamento de segredos do Render para informações sensíveis, incluindo apenas as chaves em <code>render.yaml</code>.
# render.yaml(Blueprint)— シークレットはキーのみ定義
services:
- type: web
name: my-php-app
runtime: docker
dockerfilePath: ./Dockerfile
envVars:
# 非シークレット(値を直接記載)
- key: AWS_REGION
value: ap-northeast-1
- key: AWS_S3_BUCKET
value: my-app-uploads
# シークレット(Render Dashboard で値を設定)
- key: AWS_ACCESS_KEY_ID
sync: false # sync: false でダッシュボードで手動入力
- key: AWS_SECRET_ACCESS_KEY
sync: false
# または Render の Environment Group を参照
- fromGroup: aws-credentials
disk:
name: tmp-uploads
mountPath: /tmp/uploads
sizeGB: 5
<?php
// PHP での AWS SDK を使った S3 アップロード
require 'vendor/autoload.php';
use Aws\S3\S3Client;
use Aws\Exception\AwsException;
$s3 = new S3Client([
'version' => 'latest',
'region' => getenv('AWS_REGION'),
'credentials' => [
'key' => getenv('AWS_ACCESS_KEY_ID'),
'secret' => getenv('AWS_SECRET_ACCESS_KEY'),
],
]);
function uploadToS3(array $file, string $bucket): array
{
global $s3;
$key = 'uploads/' . uniqid('file_', true) . '_' . basename($file['name']);
try {
$result = $s3->putObject([
'Bucket' => $bucket,
'Key' => $key,
'SourceFile' => $file['tmp_name'],
'ContentType' => mime_content_type($file['tmp_name']),
'ACL' => 'private',
]);
return [
'success' => true,
'key' => $key,
'url' => $result['ObjectURL'],
];
} catch (AwsException $e) {
return ['success' => false, 'error' => $e->getMessage()];
}
}
// アップロード処理
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['file'])) {
$file = $_FILES['file'];
// バリデーション
$maxSize = 50 * 1024 * 1024; // 50MB
if ($file['size'] > $maxSize) {
http_response_code(413);
echo json_encode(['error' => 'ファイルが大きすぎます(上限50MB)。']);
exit;
}
$allowedMimes = ['image/jpeg', 'image/png', 'image/webp', 'application/pdf'];
$detectedMime = mime_content_type($file['tmp_name']); // サーバー側でMIMEを検出
if (!in_array($detectedMime, $allowedMimes)) {
http_response_code(415);
echo json_encode(['error' => '許可されていないファイル形式です。']);
exit;
}
$result = uploadToS3($file, getenv('AWS_S3_BUCKET'));
echo json_encode($result);
}
Exemplo de configuração completa em render.yaml (Blueprint)
Com Blueprint, você pode gerenciar a infraestrutura do Render através de código. Você pode definir Web Service, banco de dados, Redis, disco e variáveis de ambiente em conjunto.
# render.yaml
version: "1"
services:
# Web アプリケーション
- type: web
name: file-upload-app
runtime: node
plan: starter # free / starter / standard / pro
region: singapore # oregon / frankfurt / singapore / ohio
buildCommand: npm ci && npm run build
startCommand: node server.js
healthCheckPath: /health
autoDeploy: true # Git push で自動デプロイ
# 永続ストレージ(スケールアウト不可)
disk:
name: user-uploads
mountPath: /app/data/uploads
sizeGB: 20
# 環境変数
envVars:
- key: NODE_ENV
value: production
- key: PORT
value: 3000
- key: UPLOAD_DIR
value: /app/data/uploads
- key: AWS_REGION
value: ap-northeast-1
- key: AWS_S3_BUCKET
value: my-production-bucket
# シークレット(ダッシュボードで値を設定)
- key: AWS_ACCESS_KEY_ID
sync: false
- key: AWS_SECRET_ACCESS_KEY
sync: false
- key: DATABASE_URL
fromDatabase:
name: app-db
property: connectionString
# PostgreSQL データベース
- type: pserv
name: app-db
runtime: postgres
plan: starter
region: singapore
databaseName: app_production
Arquivo de teste disponível para usar neste artigo (gratuito)
- → <a href="/ja/files/images/png/1mb/" class="text-primary-600 dark:text-primary-400 hover:underline">Imagem PNG de teste (1MB)</a> — Para verificação de operação de upload para <code>Render Disk</code> e <code>S3</code>
- → <a href="/ja/files/pdf/1mb/" class="text-primary-600 dark:text-primary-400 hover:underline">Arquivo de teste PDF (1MB)</a> — Para confirmação do funcionamento da configuração <code>upload_max_filesize</code> do PHP
- → <a href="/ja/files/zip/1mb/" class="text-primary-600 dark:text-primary-400 hover:underline">Arquivo de teste ZIP (1MB)</a> — Para teste de valor limite e validação de upload direto em S3
Artigos relacionados
- → <a href="/ja/blog/vercel-upload-config/" class="text-primary-600 dark:text-primary-400 hover:underline">Configuração e limites de upload de arquivos do Vercel | Vercel Blob, limitações de API e soluções alternativas</a>
- → <a href="/ja/blog/netlify-upload-config/" class="text-primary-600 dark:text-primary-400 hover:underline">Como fazer upload de arquivos com Netlify Functions | Limites, Large Media e soluções alternativas</a>
- → <a href="/ja/blog/laravel-file-upload/" class="text-primary-600 dark:text-primary-400 hover:underline">Guia de implementação de upload de arquivos no Laravel | Validação, Storage e suporte S3</a>