How to Upload Files with FTP: A Complete Technical Guide
File Transfer Protocol (FTP) is a network protocol operating on a client-server model that enables bidirectional file transfer between a local machine and a remote host over TCP/IP. It uses two separate channels — a control channel (port 21) for commands and a data channel (port 20 or a negotiated ephemeral port) for actual file payloads, which is a fundamental architectural detail that explains most firewall and passive-mode issues practitioners encounter.
For anyone managing a web server, deploying application code, or administering a VPS Hosting environment, mastering FTP and its secure successors is non-negotiable. This guide covers the full workflow: protocol selection, client configuration, directory navigation, batch transfers, permission management, and production-grade troubleshooting — including edge cases that generic tutorials omit.
Understanding FTP Architecture and Protocol Variants
Before touching a client, understanding which protocol variant you are actually using prevents hours of debugging later.
Active vs. Passive Mode
FTP's dual-channel design creates a critical behavioral split:
- Active mode: The server initiates the data connection back to the client on a port the client specifies. This almost always fails through NAT routers or strict firewalls because the inbound connection from the server is blocked.
- Passive mode (PASV): The client initiates both connections. The server opens a random high port and tells the client to connect to it. This is the correct default for virtually every modern deployment.
Most connection failures in production stem from active mode being used against a firewalled server, or a server whose passive port range is not open in its own firewall rules.
Protocol Comparison Table
| Feature | FTP | FTPS (FTP over TLS) | SFTP (SSH File Transfer) | SCP |
|---|---|---|---|---|
| — | — | — | — | — |
| Encryption | None | TLS/SSL | SSH | SSH |
| Control channel port | 21 | 21 (explicit) / 990 (implicit) | 22 | 22 |
| Data channel | Separate (20/ephemeral) | Separate (TLS-wrapped) | Single multiplexed channel | Single channel |
| Firewall friendliness | Poor | Poor | Excellent | Excellent |
| Resume transfers | Yes (REST command) | Yes | Yes | No |
| Directory listing | Yes | Yes | Yes | No |
| Certificate required | No | Yes (server-side minimum) | No (key or password) | No |
| Recommended for production | No | Situational | Yes | Yes (bulk copy) |
The practical takeaway: Use SFTP by default. Use FTPS only when a legacy system explicitly requires it. Avoid plain FTP entirely on any internet-facing server — credentials and file contents travel in cleartext and are trivially intercepted.
Prerequisites and Credential Gathering
Before opening any client, collect the following from your hosting provider or server administrator:
- Hostname or IP address — e.g.,
ftp.yourdomain.comor203.0.113.45 - Protocol — FTP, FTPS (explicit or implicit), or SFTP
- Port — 21 for FTP/FTPS-explicit, 990 for FTPS-implicit, 22 for SFTP
- Username and password — or an SSH private key for SFTP key-based authentication
- Remote root path — commonly
/public_html,/var/www/html, or/home/username/public_htmldepending on the server stack
If you are working with a VPS with cPanel, your FTP credentials are created under cPanel > FTP Accounts, where you can also scope each account to a specific directory — a security practice that limits blast radius if credentials are compromised.
Step 1: Install and Configure FileZilla
FileZilla remains the most widely deployed cross-platform FTP client due to its support for FTP, FTPS, and SFTP, its built-in Site Manager, and its transfer queue with resume capability.
Download: Obtain FileZilla Client (not Server) from filezilla-project.org. Verify the SHA-512 checksum published on the download page before executing the installer — this is a step most tutorials skip, but supply-chain attacks on popular utilities are documented.
After installation, open FileZilla and navigate to Edit > Settings > Transfers > File Types. Set the default transfer type to Binary, not Auto. Auto-detect can silently corrupt binary files (images, archives, executables) by applying line-ending conversion when the heuristic misclassifies the file.
Step 2: Create a Site Manager Entry
Using the Quickconnect bar is acceptable for one-off tasks, but it stores credentials in plaintext in recentservers.xml. For any recurring connection, use the Site Manager instead.
- Open File > Site Manager (or press
Ctrl+S). - Click New Site and give it a descriptive name.
- Configure the General tab:
- Protocol: Select SFTP for SSH-based servers, or FTP with explicit TLS for FTPS.
- Host: Enter the server hostname or IP.
- Port: Leave blank to use the protocol default, or specify explicitly.
- Logon Type: Choose Normal for password auth, or Key file for SSH key-based SFTP.
- User / Password: Enter credentials.
- On the Advanced tab, set the Default remote directory to your web root (e.g.,
/public_html) and the Default local directory to your project folder. This eliminates navigation time on every session. - Click Connect.
For SFTP with key-based authentication — the recommended approach for Dedicated Servers — point the Key file field to your private key (.pem or .ppk format). FileZilla uses its own key format; convert OpenSSH keys with PuTTYgen if needed.
Step 3: Navigate the Dual-Pane Interface
Once connected, FileZilla presents a split view:
- Left pane (Local Site): Your local filesystem. Navigate to the directory containing files you want to upload.
- Right pane (Remote Site): The server's filesystem. Navigate to the target directory — typically
/public_htmlfor web content. - Bottom queue panels: Show queued transfers, failed transfers, and successful transfers with timestamps and byte counts.
The directory tree at the top of each pane and the file list below it are independent — clicking a folder in the tree does not automatically scroll the file list. This catches new users who wonder why their file list appears empty.
Step 4: Upload Files
Single File or Manual Selection
Right-click any file in the local pane and select Upload, or drag it to the remote pane. For multi-file selection, use Ctrl+Click (Windows/Linux) or Cmd+Click (macOS) for non-contiguous selection, or Shift+Click for a range.
Drag-and-Drop Upload
Select files in the local pane and drag them to the target folder in the remote pane. FileZilla queues all items and begins transferring immediately.
Synchronized Directory Upload
For deploying an entire project directory, right-click the local folder and choose Upload. FileZilla recursively uploads all contents, preserving the directory structure on the remote side.
Monitoring Transfer Progress
The transfer queue at the bottom shows:
- Filename and size
- Transfer speed (bytes/second)
- Elapsed and estimated time
- Remote destination path
A transfer that completes but shows 0 bytes transferred is a silent failure — the file was created but is empty. This typically indicates a permissions issue on the destination directory or a disk quota violation on the server.
Step 5: Set Correct File Permissions After Upload
This is the most commonly skipped step and the source of a significant percentage of "my website is broken after upload" support tickets.
After uploading, right-click a file or directory in the remote pane and select File permissions. The numeric representation maps directly to Unix permission octets:
- 644 — Standard for web files (owner read/write, group/other read-only)
- 755 — Standard for directories and executable scripts
- 600 — Private files that should not be web-accessible (e.g., configuration files with credentials)
- 777 — Never use this in production; it grants world-write access
For a recursive permission fix on an entire uploaded directory tree, check Recurse into subdirectories and apply 644 to files and 755 to directories separately. FileZilla does not differentiate files from directories in a single recursive pass — you must run it twice with the appropriate filter selected.
Alternatively, after connecting via SSH, fix permissions in bulk:
find /public_html -type f -exec chmod 644 {} ;
find /public_html -type d -exec chmod 755 {} ;Step 6: Verify the Upload
Do not assume a completed transfer queue means the deployment is correct. Perform these verification steps:
- In FileZilla: Refresh the remote directory (
F5or right-click > Refresh) and confirm file sizes match the local originals. A size mismatch indicates a truncated transfer. - Via browser: Load the updated page and perform a hard refresh (
Ctrl+Shift+R) to bypass the browser cache. - Via SSH: For server-side verification, compare checksums:
md5sum /public_html/index.htmlCompare the output against the local file's checksum. A mismatch means the file was corrupted in transit — rare with SFTP but possible with plain FTP on unstable connections.
Advanced Techniques and Production Patterns
Resuming Failed Transfers
If a large file transfer is interrupted, FileZilla uses the FTP REST command (or SFTP's equivalent) to resume from the last confirmed byte offset. In the Failed transfers tab, right-click the failed item and select Reset and requeue failed files, then start the queue again. This works reliably with SFTP; plain FTP resume depends on server support for the REST command.
Excluding Files from Upload
FileZilla's Edit > Filename Filters lets you define rules to exclude files matching patterns — for example, excluding .git directories, node_modules, .DS_Store, or .env files from accidental upload. This is a critical safeguard: uploading a .env file containing database credentials or API keys to a public web root is a serious security incident.
Scripted/Automated FTP Transfers
For CI/CD pipelines or scheduled deployments, the FileZilla GUI is not appropriate. Use the command-line lftp utility instead:
lftp -u username,password sftp://your-server.com << 'EOF'
set sftp:auto-confirm yes
mirror --reverse --delete --verbose /local/project/ /public_html/
EOFThe --reverse flag uploads (local to remote), --delete removes remote files not present locally (use with caution), and --verbose logs every operation. This pattern is suitable for automated deployments on VPS Hosting environments where SSH access is available.
Using rsync Over SSH as an FTP Alternative
For large deployments or incremental syncs, rsync over SSH is dramatically more efficient than FTP because it transfers only the changed blocks within files, not entire files:
rsync -avz --progress --delete /local/project/ user@your-server.com:/public_html/-a — Archive mode (preserves permissions, timestamps, symlinks)
-v — Verbose output
-z — Compress data during transfer
--delete — Remove remote files deleted locally
rsync requires SSH access and is not available through shared hosting control panels, but it is the correct tool for any environment where you control the server stack.
Troubleshooting Common FTP and SFTP Issues
Connection Timeout or Refused
Verify the hostname resolves correctly: nslookup ftp.yourdomain.comtelnet your-server.com 21 or nc -zv your-server.com 22iptables -L or ufw status will show whether the port is permittedsystemctl status sshd530 Login Authentication Failed
- Confirm the username is exact — FTP usernames are case-sensitive on Linux systems
- Verify the account is not locked:
passwd -S usernameon the server - Check
/var/log/auth.logor/var/log/securefor the rejection reason - If using cPanel, confirm the FTP account has not expired or been suspended
550 Permission Denied on Upload
The remote directory does not grant write access to the authenticated FTP user. Check ownership and permissions:
ls -la /public_html/If the directory is owned by a different user, either adjust ownership (chown) or grant group-write permission (chmod g+w). On shared hosting, this is handled through the hosting control panel's file manager.
Passive Mode Connection Failures
If you see "Could not retrieve directory listing" after a successful login, the server's passive port range is not reachable. In FileZilla, go to Edit > Settings > FTP > Passive mode and try Fall back to active mode. On the server side, ensure the passive port range (commonly 49152–65534) is open in the firewall and correctly configured in the FTP daemon's settings (e.g., pasv_min_port and pasv_max_port in vsftpd.conf).
Binary vs. ASCII Transfer Corruption
PHP files uploaded in ASCII mode on a Windows client may have Windows-style line endings (rn) converted, which can break certain parsers. Confirm FileZilla is set to Binary mode under Transfer > Transfer Type > Binary.
Alternative Upload Methods
FTP is not always the right tool. The following alternatives are worth knowing:
cPanel / Plesk File Manager: Available through the web-based control panel on Shared Web Hosting and VPS Control Panels. Suitable for small edits and single-file uploads. Has a 2 GB file size limit in most implementations and is not suitable for bulk transfers.
SCP (Secure Copy): A simple, scriptable SSH-based copy tool. No resume capability, no directory listing, but extremely reliable for one-shot transfers:
scp -r /local/project/ user@your-server.com:/public_html/Git-based deployment: Push to a bare repository on the server and use a post-receive hook to check out files into the web root. This is the cleanest deployment pattern for code — it provides version history, rollback capability, and eliminates manual file management entirely.
Object storage / CDN sync: For static assets, syncing to an S3-compatible bucket and serving via CDN is more scalable than FTP-based deployment and removes the web server from the static asset delivery path entirely.
Quick Decision Matrix: Choosing the Right Transfer Method
| Scenario | Recommended Method |
|---|---|
| — | — |
| One-off file edit on shared hosting | cPanel File Manager |
| Regular website deployment, no SSH | SFTP via FileZilla |
| Automated CI/CD pipeline deployment | `lftp` or `rsync` over SSH |
| Large binary file, one-time transfer | `scp` |
| Incremental code deployment | `rsync` or Git post-receive hook |
| Legacy system requiring FTP | FTPS (explicit TLS) minimum |
| Bulk static asset deployment | S3-compatible object storage sync |
Key Technical Checklist Before Going Live
- Protocol: SFTP or FTPS only — never plain FTP on a production server
- Credentials: Use dedicated FTP/SFTP accounts scoped to the minimum required directory, not root or the primary system user
- Transfer mode: Binary, not Auto or ASCII
- File permissions: 644 for files, 755 for directories — verified post-upload
- Sensitive files: Confirm
.env,.git/,node_modules/, and config files with credentials are excluded from upload via filename filters - Checksum verification: MD5 or SHA-256 comparison for critical files after transfer
- Passive mode: Enabled by default in the FTP client
- SSH keys: Use key-based authentication for SFTP on any server you control; disable password authentication in
sshd_configwhere possible
Frequently Asked Questions
What is the difference between FTP and SFTP?
FTP transmits data and credentials in plaintext over two separate TCP channels (control on port 21, data on port 20 or ephemeral). SFTP is a completely different protocol built on top of SSH that multiplexes everything through a single encrypted channel on port 22. They share a name but share no protocol code.
Why does FileZilla show "Connection timed out" even with correct credentials?
A timeout before authentication typically means the server port is unreachable — blocked by a firewall, the service is not running, or the hostname does not resolve to the correct IP. A timeout after authentication usually indicates a passive mode problem where the data channel port range is firewalled. Check server-side firewall rules and confirm the passive port range is open.
Can I use FTP to upload files to a VPS without a control panel?
Yes. Install an SFTP-capable SSH daemon (OpenSSH, which is standard on all Linux distributions) — no additional FTP server software is required. Connect with FileZilla using the SFTP protocol on port 22 and your SSH credentials or key pair. This is the recommended approach for any VPS Hosting environment.
What file permissions should WordPress files have after FTP upload?
WordPress core files should be 644, directories 755, and wp-config.php should be 600 (owner read/write only). The wp-content/uploads directory requires 755 or 775 for the web server to write uploaded media. Never set any WordPress directory to 777.
Is there a file size limit when uploading via FTP?
FTP and SFTP themselves impose no inherent file size limit — transfers are streamed. Practical limits come from server-side disk quotas, PHP upload_max_filesize (irrelevant for FTP, which bypasses PHP entirely), or filesystem limits (ext4 supports files up to 16 TB). For Shared Web Hosting, the hosting provider may enforce a disk quota that caps total storage rather than individual file size.
