Search code examples
phpfpdf

How to save unique filename to directory with FPDF?


I would like to save each newly generated PDF file with a unique filename to the "receipts" directory after generating the PDF using the FPDF library... As it is now, the PDF is overwritten each time. Can I append a time-stamp to the PDF filename? Example --->( /receipt_month-day-year-hour-seconds.pdf )

Absolute uniqueness desired, but not super critical.

$pdf->Output('receipts/receipt.pdf', 'F');

Solution

  • An easy (but not foolproof) way of ensuring a filename is unique would be to add a microtime timestamp to the filename. Microtime includes thousanths of a second, so would probably work unless your site has a lot of traffic:

    $pdf->Output('receipts/receipt-' . microtime(true) . '.pdf', 'F');
    

    If you want your timestamp to be like receipt_12-26-2017.pdf, then:

    $pdf->Output('receipts/receipt_' . date("m-d-Y") . '.pdf', 'F');
    

    If you really want to ensure your filenames are unique per directory, you could do something like this:

    <?php
    
    function get_filenames($source_dir, $include_path = FALSE, $_recursion = FALSE)
    {
        static $_filedata = array();
    
        if ($fp = @opendir($source_dir))
        {
            // reset the array and make sure $source_dir has a trailing slash on the initial call
            if ($_recursion === FALSE)
            {
                $_filedata = array();
                $source_dir = rtrim(realpath($source_dir), DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR;
            }
    
            while (FALSE !== ($file = readdir($fp)))
            {
                if (@is_dir($source_dir.$file) && strncmp($file, '.', 1) !== 0)
                {
                    get_filenames($source_dir.$file.DIRECTORY_SEPARATOR, $include_path, TRUE);
                }
                elseif (strncmp($file, '.', 1) !== 0)
                {
                    $_filedata[] = ($include_path == TRUE) ? $source_dir.$file : $file;
                }
            }
            return $_filedata;
        }
        else
        {
            return FALSE;
        }
    }
    
    function force_unique_filename( $dir_list, $file_name, $x = 2 )
    {
        /**
         * Dir list may be an array of file names, or in the case of 
         * cURL, the list may be supplied as a string. If an array, we 
         * just convert the array to a string so it is checked as a string.
         */
        if( is_array( $dir_list ) )
        {
            $dir_list = implode( ' ', $dir_list );
        }
    
        while( strpos( $dir_list, $file_name ) !== FALSE )
        {
            // Use pathinfo to break apart the filename
            $info = pathinfo( $file_name );
    
            // Get the file extension of the file
            $ext = '.' . $info['extension'];
    
            // Get the name of the file without extension
            $file_name = basename( $file_name, $ext );
    
            // Remove the filename suffix before adding a new one
            $pattern = '/\(\d+\)/';
            $replacement = '';
            $file_name = preg_replace( $pattern, $replacement, $file_name );
    
            // Add new filename suffix
            $file_name .= '(' . (string) $x . ')' . $ext;
    
            // Increment the number we are using in a filename suffix "($x)"
            $x++;
        }
    
        return $file_name;
    }
    
    // -----------------------------------------------------------------------
    
    // This directory should be an absolute path...
    $source_dir = './receipts';
    
    // The desired filename
    $filename = 'receipt_' . date("m-d-Y") . '.pdf';
    
    // Get all of the filenames in this directory
    $filenames = get_filenames( $source_dir, FALSE, FALSE );
    
    // Get the unique filename
    $unique_filename = force_unique_filename( $filenames, $filename );
    
    $pdf->Output('receipts/' . $unique_filename, 'F');