How to get the file to download


#1

I have a form on a web site to submit/upload recorded webcam video files. And then an email, with a file link (to the uploaded file) is sent. It all works successfully. When I access my email to see the arrived message, (via pc) and select the link (to the video file), it automatically plays on my pc, I’m looking for a way to have it so when the link is selected the file downloads, not automatically plays. Any help will be appreciated. Here’s the submit.php file:

<?php
if($_POST){
	$to = 'form@....com';
	$subject = 'NewForm';
	$name = $_POST['name'];
	$email = $_POST['email'];
	$message = $_POST['message'];
	$headers = $name;

	$message .= "Hello ".$_POST[name]." - Here is the link to your video: ".$_POST[videolink].". Created by ".$_POST['email']." ";
	header('Location: https://....com');
   exit;
}
?>

#2

You need to add a HTTP header added to the response on the URL where the video is.

How is the video served? PHP? Apache? Nginx?


#3

In PHP you can do this with a Content-Disposition header.
See this first example here, it shows how it’s done with a PDF.


#4

Thanks for your replies and I read the link provided.
I tried, without success, because I don’t know what to add into the filename, because it’s name is randomly generated upon upload, via js:

<?php
header('Content-Disposition: attachment; filename=""');

" " " "

?>

So, any additional help to get the file to download, instead of link to play will be welcomed.


#5

Where did you put that code?


#6

So you are trying to download a file you don’t know the name of? :thinking:


#7

However it’s generated, you must be storing the filename somewhere in the database so that you can retrieve it. If you’re storing the complete URL for some reason, then you’ll have to strip that out as the parameter should not contain a complete path, only a filename.

The filename you specify here is just a basis for what the file will be called when the user saves it - don’t forget the user could change that. For testing purposes, you could stick any valid video filename string in there. It’s nothing to do with what the file is called on your server, which you must already know as your next bit of code after the header will be to output the file contents.


#8

So just to be clear, is the url in $_POST[videolink] a direct link to the video file or to another php page that serves the video?


#9

Thank you for all your replies.
This file is part of the uploading:

<?php

foreach(array('video', 'audio') as $type) {
if (isset($_FILES["${type}-blob"])) {
$fileName = $_POST["${type}-filename"];

$uploadDirectory = 'upload/'.$fileName;
if (!move_uploaded_file($_FILES["${type}-blob"]["tmp_name"], $uploadDirectory)) {
echo("problem moving uploaded file");
}
else{
echo ('https://...com/upload/'.$fileName);
}
}
}
?>

Maybe? I need to incorporate $fileName into this:

<?php
if($_POST){
	$to = 'form@....com';
	$subject = 'NewForm';
	$name = $_POST['name'];
	$email = $_POST['email'];
	$message = $_POST['message'];
	$headers = $name;

	$message .= "Hello ".$_POST[name]." - Here is the link to your video: ".$_POST[videolink].". Created by ".$_POST['email']." ";
	header('Location: https://....com');
   exit;
}
?>

or replace video with $fileName?

any additional guidance will be appreciated.


#10

I really, absolutely, unequivocally don’t care how the file ends up on your server. It has nothing to do with how it is downloaded.

What is serving the video to users when they click the link?


#11

Instead of having the link in the e-mail be a direct link to the actual filename, you want it to point to a seperate php page that only handles setting the header appropriately and then reading and passing along the return the data from the file. Have a look at Example #1 from this page:

<?php
$file = 'monkey.gif';

if (file_exists($file)) {
    header('Content-Description: File Transfer');
    header('Content-Type: application/octet-stream');
    header('Content-Disposition: attachment; filename="'.basename($file).'"');
    header('Expires: 0');
    header('Cache-Control: must-revalidate');
    header('Pragma: public');
    header('Content-Length: ' . filesize($file));
    readfile($file);
    exit;
}
?>

Let’s say you create a page like this call it download.php
This example is almost exactly what you need, except that the filename is hardcoded, right?
So the question is, how do you tell download.php which file you want to download? It would have to be through a query parameter that you pass in the link in the email.
So a generated email message would contain something like:

Hello John - Here is the link to your video: https://....../download.php?somevar=someval

And in download.php you would $_GET['somevar'] and use it to decide which file to serve.

But what exactly should you pass to the page?

The quick and dirty solution would be to just pass the actual filename. So the url in th e-mail would look something like https://....../download.php?file=my%20urlencoded%20filename.mpg and in download.php you could just do something like:
$file = urldecode($_GET['file'])

A much safer, but slightly more complicated solution would be to do what @droopsnoot suggested and have a database table where you store each of the paths for each uploaded file against a unique id. Your links would look something like https://....../download.php?id=1
and in dowload.php you would retrieve the actual filename from the table where the id column is $_GET['id']

Hope that makes sense.


Not show the whole path/link, but still keep the ability to click it to download the file
#12

That code is very dangerous, as it doesn’t impose any limits on the path. I could go to download.php?file=/etc/passwd and download the information on all users in your system.

Using an id is already a lot better.

But you don’t need to use php at all. If you put all videos in the same directory, you can set headers for all files in that directory using the webserver, which is a lot better at serving files than php is.


#13

Thanks for all the replies. All files are currently uploaded to the ‘upload’ folder on the server. How do I “set headers for all files in that directory using the webserver”?


#14

Depends. What web server are you using?

(note that I already asked that in post #2 …)


#15

Linux


#16

That’s an operating system, not a web server.


#17

Dedicated


#18

That’s the type of hosting you have.

The server will be Apache, or Nginx, or lighttpd, or …


#19

Apache


#20

Put the following in your .htaccess:

<Files *.mp4>
    ForceType applicaton/octet-stream
</Files>

Assuming your videos are mp4. Otherwise you need to change the extension.