Email download link of a file – PHP and MySQL

In this tutorial, we are going to show you, how you can email a download link of a file to a user when they request to download files from your website. We are going to create a system where you can upload files and the user will be able to download them. But before downloading, they must enter their email address. The link to download the file will be emailed to the user. In this way, you will get a large number of emails. This will help you with a very large email list.

Prevent direct access to files

First, we are going to prevent users from downloading the files directly from the URL. We will be storing all our uploaded files in the “uploads” folder. So, create a new folder named “uploads” at the root of your project. Create a “.htaccess” file in this folder. In this file, write the following single line:

deny from all

This will gives a “403 Forbidden” error whenever someone tries to access the file directly from the browser.

Upload files

Now we are going to create a form that will allow you to upload files. You can create this form in your admin panel because usually, the administrator of the website can upload files.

<form method="POST" action="index.php" enctype="multipart/form-data">
    <input type="file" name="file" required />
    <input type="submit" name="upload" value="Upload" />
</form>

Create a database named “collect_emails_while_downloading_files” in your phpMyAdmin. Or you can use your own database if you already have one. In this database, you need to create a table where we will store the path and name of all uploaded files.

CREATE TABLE files (
	id INTEGER(11) PRIMARY KEY AUTO_INCREMENT NOT NULL,
	file_name TEXT NOT NULL,
    file_path TEXT NOT NULL
);

Then we need to save the selected file in the uploads folder and its path in the files table in the MySQL database. We will be using PHP PDO prepared statements that will help us from preventing the SQL injection.

<?php

    // connect with database
    $conn = new PDO("mysql:host=localhost:8889;dbname=collect_emails_while_downloading_files", "root", "root");

    // check if form is submitted, for admin panel only
    if (isset($_POST["upload"]))
    {
        // get the file
        $file = $_FILES["file"];
        
        // make sure it does not have any error
        if ($file["error"] == 0)
        {
            // save file in uploads folder
            $file_path = "uploads/" . $file["name"];
            move_uploaded_file($file["tmp_name"], $file_path);

            // save file path in database, prevent SQL injection too
            $sql = "INSERT INTO files(file_name, file_path) VALUES (:file_name, :file_path)";
            $result = $conn->prepare($sql);
            $result->execute([
                ":file_name" => $file["name"],
                ":file_path" => $file_path
            ]);
        }
        else
        {
            die("Error uploading file.");
        }
    }

    // get all files
    $sql = "SELECT * FROM files ORDER BY id DESC";
    $result = $conn->query($sql);
    $files = $result->fetchAll();

?>

Refresh the page and try uploading a file. You will see it will be saved in your uploads folder and its path and name will be stored in the files table. Also, try accessing that from the browser directly, it will give you a 403 Forbidden error.

Show all uploaded files

In the previous step, we ran a query to fetch all files sorting from latest to oldest. Now we need to show them on a table.

<table>
    <thead>
        <tr>
            <th>ID</th>
            <th>Name</th>
            <th>Action</th>
        </tr>
    </thead>

    <tbody>
        <?php foreach ($files as $file): ?>
            <tr>
                <td><?php echo $file["id"]; ?></td>
                <td><?php echo $file["file_name"]; ?></td>
                <td>
                    <!-- button to download file -->
                    <form method="POST" action="check-email.php" onsubmit="return onFormSubmit(this);">
                        <input type="hidden" name="id" value="<?php echo $file['id']; ?>" required />
                        <input type="hidden" name="email" />
                        <input type="submit" value="Download" />
                    </form>
                </td>
            </tr>
        <?php endforeach; ?>
    </tbody>
</table>

This will show all files in a table with a button to download. When that button is clicked, we need to get the user’s email address so we can email him a download link for that file. That link will be valid for that file and for that email only.

<script>
    function onFormSubmit(form) {
        // get email address and submit
        var email = prompt("Enter your email:", "");
        if (email != null && email != "") {
            form.email.value = email;
            return true;
        }
        return false;
    }
</script>

Send download link in email

We will be using the PHPMailer library to send emails. Open CMD at the root folder of your project and run the following command. Make sure you have the composer downloaded and installed in your system.

composer require phpmailer/phpmailer

Create a table in your database that will store all the download requests of files sent by users. Run the following query in your database in phpMyAdmin:

CREATE TABLE download_requests (
	id INTEGER(11) PRIMARY KEY AUTO_INCREMENT NOT NULL,
	file_id INTEGER(11) NOT NULL,
	email TEXT NOT NULL,
	token TEXT NOT NULL,
	CONSTRAINT fk_file_id FOREIGN KEY (file_id) REFERENCES files (id) ON DELETE CASCADE ON UPDATE CASCADE
);

Create a file named “check-email.php” and write the following code in it. It will send the email to the user and also will store the data in the above created table.

<?php

    // composer require phpmailer/phpmailer

    // include PHPMailer library
    use PHPMailer\PHPMailer\PHPMailer;
    use PHPMailer\PHPMailer\SMTP;
    use PHPMailer\PHPMailer\Exception;
    
    require 'vendor/autoload.php';

    // connect with database
    $conn = new PDO("mysql:host=localhost:8889;dbname=collect_emails_while_downloading_files", "root", "root");

    // get all form values
    $id = $_POST["id"];
    $email = $_POST["email"];

    // generate a unique token for this email only
    $token = time() . md5($email);

    // get file from database
    $sql = "SELECT * FROM files WHERE id = :id";
    $result = $conn->prepare($sql);
    $result->execute([
        ":id" => $id
    ]);
    $file = $result->fetch();
    
    if ($file == null)
    {
        die("File not found");
    }

    // insert in download requests, prevent SQL injection too
    $sql = "INSERT INTO download_requests(file_id, email, token) VALUES (:id, :email, :token)";
    $result = $conn->prepare($sql);
    $result->execute([
        ":id" => $id,
        ":email" => $email,
        ":token" => $token
    ]);

    // send email to user
    $mail = new PHPMailer(true);

    try
    {
        $mail->SMTPDebug = 0;
        $mail->isSMTP();
        $mail->Host = 'smtp.gmail.com';
        $mail->SMTPAuth = true;
        $mail->Username = 'your_email@gmail.com';
        $mail->Password = 'your_password';
        $mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
        $mail->Port = 587;

        $mail->setFrom('adnan@gmail.com', 'Adnan');
        $mail->addAddress($email); // Add a recipient
        $mail->addReplyTo('adnan@gmail.com', 'Adnan');

        // Content
        $mail->isHTML(true);
        $mail->Subject = 'Download your files';

        // mention download link in the email
        $email_content = "Kindly click the link below to download your files: <br />";
        $base_url = "http://localhost:8888/tutorials/collect-emails-while-downloading-files-php-mysql";
        $email_content .= "<a href='" . $base_url . "/download.php?email=" . $email . "&token=" . $token . "'>" . $file['file_name'] . "</a>";
        $mail->Body = $email_content;

        $mail->send();
        echo '<p>Link to download files has been sent to your email address: ' . $email . '</p>';
    }
    catch (Exception $e)
    {
        die("Message could not be sent. Mailer Error: " . $mail->ErrorInfo);
    }

Make sure to change the base URL at line 68. Also, change your email address and password on lines 53 and 54 respectively. This email will be used to send the emails. Goto this link and enable a less secure apps option for that email address.

Enable less secure apps – Gmail

Test the code now. You will be able to see a list of all uploaded files with a button to download. When clicked, it will show a prompt where you can enter your email address. When clicked “OK”, it will send an email with a download link and also it will store it in the “download_requests” table in the MySQL database.

In your email, you will see a link to download the file. But right now it will give a 404 Not found error because the file is not created yet.

Download the file from email download link

Create a file named “download.php” and write the following code in it. This will directly download the file into your system.

<?php

    // connect with database
    $conn = new PDO("mysql:host=localhost:8889;dbname=collect_emails_while_downloading_files", "root", "root");

    // get variables from email
    $email = $_GET["email"];
    $token = $_GET["token"];

    // check if the download request is valid
    $sql = "SELECT *, download_requests.id AS download_request_id FROM download_requests INNER JOIN files ON files.id = download_requests.file_id WHERE download_requests.email = :email AND download_requests.token = :token";
    $result = $conn->prepare($sql);
    $result->execute([
        ":email" => $email,
        ":token" => $token
    ]);
    $file = $result->fetch();

    if ($file == null)
    {
        die("File not found.");
    }

    // download the file
    $url_encoded_file_name = rawurlencode($file["file_name"]);
    $file_url = "http://localhost:8888/tutorials/collect-emails-while-downloading-files-php-mysql/uploads/" . $url_encoded_file_name;
    // die($file_url);

    // headers to download any type of file
    header('Content-Description: File Transfer');
    header('Content-Type: application/octet-stream');
    header('Content-Disposition: attachment; filename="' . $file["file_name"] . '"');
    header('Expires: 0');
    header('Cache-Control: must-revalidate');
    header('Pragma: public');
    header('Content-Length: ' . filesize($file["file_path"]));
    readfile($file["file_path"]);

Make sure to change your base URL at line 26. Now you can run a complete test cycle again. Upload a file, click the download button, and enter your email. Check your email and then click the download link from the email and the file will be downloaded. Verify the file that is downloaded correctly.

So that’s how you can collect a large number of emails by allowing people to simply download files. You can create a very large email list from it.

Learn how to send attachment with an email using PHP.

Attach files in email – PHP

[wpdm_package id=’1281′]

Upload file along with other input fields – Node JS

So we are going to teach you how you can upload the file from HTML form along with other input fields in Node JS. We will be using NPM’s formidable, fs (file system) and EJS modules. We will create an input type file to select a file from computer and input type text, the file will be store in server with the name I enter in text box.

Let’s get started

Open command prompt in your project’s root folder and run the following command to install necessary modules:

npm install express http formidable fs ejs
  • Express and HTTP will be used to start the server
  • formidable will be used to handle the input file
  • fs (file system) will be used to save the file
  • EJS will be used to render the HTML page

Now create a file named index.js and paste the following code in it:

var express = require("express");
var app = express();
var http = require("http").createServer(app);
var formidable = require("formidable");
var fs = require("fs");

app.set("view engine", "ejs");

http.listen(4000, function () {
	app.get("/", function (request, result) {
		result.render("index");
	});
});

It will start the server at port number 4000 and creates a default route which when access will render the index.ejs page. We will create that file in a moment. We are setting the default template engine to EJS, don’t worry if you are using any other engine, the core login will remain the same.

Start the server

To start the server, simply run the following command in your command prompt which should be opened in your project’s root folder:

npm install -g nodemon
nodemon index.js

Now you can access your server by running the following URL in your browser:
http://localhost:4000/

Display input type file

Now create a folder in your project named “views”. Your all HTML files should be placed inside this folder and all files must end with an extension .ejs. Create a file named index.ejs inside this views folder. The name of the file must be the same as in render function above, along with .ejs extension at the end. Paste the following code in that file. It will create a form with an input field to select a file and an input field to enter text. We will save the uploaded file with the name entered in text box.

<form method="POST" action="/upload" enctype="multipart/form-data">
	<input type="file" name="file">
	<input type="text" name="fileName" placeholder="File name">

	<input type="submit">
</form>

Save file on server

Make sure the method is POST and encoding type must be attached, otherwise, the file will not be sent. Action attribute will specify the route where data should be sent. So paste the following code in your index.js file right below the “/” route:

app.post("/upload", function (request, result) {
	var formData = new formidable.IncomingForm();
	formData.parse(request, function (error, fields, files) {
		var extension = files.file.name.substr(files.file.name.lastIndexOf("."));
		var newPath = "uploads/" + fields.fileName + extension;
		fs.rename(files.file.path, newPath, function (errorRename) {
			result.send("File saved = " + newPath);
		});
	});
});

Now you just need to create a folder named “uploads” and when you select the file. Enter the name, the file will be saved with the name you enter in the text field. That’s how you can upload a file on Node JS server.

[wpdm_package id=’245′]