Esas cosas se suelen hacer con sessiones. Son muy parecidas a los captchas. Te dejo un ejemplo:
generar.php<?php
$nombre_archivo = 'archivo.txt';
$link = 'http://mipagina.com/descargar.php';
// Generar un hash en sha1 totalmente aleatorio.
// Poner el hash en session para futura comprobación.
$_SESSION['link'][$nombre_archivo] = $sesc;
echo '<h1>Tu archivo esta listo</h1>';
echo $link.'?archivo='.$nombre_archivo.'&sesc='.$sesc;
?>
Esto generaría un enlace del siguiente tipo:
http://mipagina.com/descargar.php?archivo=archivo.txt&sesc=7c44781daa257c8931fed1f0eb79f4c8a0bc98a0
descargar.php<?php
// Si sesc o archivo estan vacios, morrimos.
if(empty($_GET['sesc']) || empty($_GET['archivo'])){ die('Consulta no valida. SESC o ARCHIVO faltan.'); }
// Si la session del usuario no coincide con la que nos envia... morrimos.
elseif($_GET['sesc']!==@$_SESSION['link'][$_GET['archivo']]){ die('Tu session no es valida.'); }
// Destruir la session para que no pueda volver a utilizar el mismo enlace.
unset($_SESSION['link'][$_GET['archivo']]);
// Descarga de archivo.
header('Content-Type: application/octet-stream'); header("Content-disposition: attachment; filename=\"".$_GET['archivo']."\"");
?>
PD: Obviamente
este código es mega-super-hiper inseguro. Pero tu ya tendrás la manera de generar los archivos y tal así que te lo muestro como ejemplo.
PD2: Como ta ha mencionado @engelx, si vas a utilizar usuarios y quieres que los enlaces sean permanentes para ellos tendrás que almacenar el valor en la base de datos.
Saludos