I am trying to attach a pdf file to a custom post type.
I have found this snippet at wpsnipp.com.
The code does the trick, but only for posts.
I have a custom post type named 'events' and I can't make it work.

add_action("admin_init", "pdf_init");
add_action('save_post', 'save_pdf_link');
function pdf_init(){
    add_meta_box("my-pdf", "PDF Document", "pdf_link", "post", "normal", "low");
function pdf_link(){
    global $post;
    $custom  = get_post_custom($post->ID);
    $link    = $custom["link"][0];
    $count   = 0;
    echo '<div class="link_header">';
    $query_pdf_args = array(
            'post_type' => 'attachment',
            'post_mime_type' =>'application/pdf',
            'post_status' => 'inherit',
            'posts_per_page' => -1,
    $query_pdf = new WP_Query( $query_pdf_args );
    $pdf = array();
    echo '<select name="link">';
    echo '<option class="pdf_select">SELECT pdf FILE</option>';
    foreach ( $query_pdf->posts as $file) {
       if($link == $pdf[]= $file->guid){
          echo '<option value="'.$pdf[]= $file->guid.'" selected="true">'.$pdf[]= $file->guid.'</option>';
          echo '<option value="'.$pdf[]= $file->guid.'">'.$pdf[]= $file->guid.'</option>';
    echo '</select><br /></div>';
    echo '<p>Selecting a pdf file from the above list to attach to this post.</p>';
    echo '<div class="pdf_count"><span>Files:</span> <b>'.$count.'</b></div>';
function save_pdf_link(){
    global $post;
    if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE){ return $post->ID; }
    update_post_meta($post->ID, "link", $_POST["link"]);
add_action( 'admin_head', 'pdf_css' );
function pdf_css() {
    echo '<style type="text/css">
            border-top:solid 1px #e5e5e5;
            padding:6px 6px 6px 12px;
            margin:0px -6px -8px -6px;
            -moz-border-radius:0px 0px 6px 6px;
            -webkit-border-radius:0px 0px 6px 6px;
            border-radius:0px 0px 6px 6px;
    .pdf_count span{color:#666;}
function pdf_file_url(){
    global $wp_query;
    $custom = get_post_custom($wp_query->post->ID);
    echo $custom['link'][0];

And to display the link in the theme:

<? pdf_file_url(); ?>

I changed the post type from 'post' to 'events' and the meta box appears in the 'events' page.
So far so good.
It does save the pdf the first time around. And also it displays the correct link.
But then if I try to change the pdf it doesn't save it. It displays the first one again.

  • What is use of $pdf array? If not required remove it and see if it works. Jun 21 '13 at 7:38
  • Thank you. Apparently it was of no use. Commented it out, nothing changed. Still the same problem though.
    – belacqua16
    Jun 21 '13 at 8:00

Here this is my code which i used in my wordpress site in custom post type for adding the pdf to the post and its work for me try to change its and use it. Hope it will help

function add_custom_meta_boxes() {  
    add_meta_box('wp_custom_attachment', 'Hotel Brochure', 'wp_custom_attachment', 'hotel_post', 'normal', 'high');  
add_action('add_meta_boxes', 'add_custom_meta_boxes');  

function wp_custom_attachment() {  
    wp_nonce_field(plugin_basename(__FILE__), 'wp_custom_attachment_nonce');
    $html = '<p class="description">';
    $html .= 'Upload your PDF here.';
    $html .= '</p>';
    $html .= '<input type="file" id="wp_custom_attachment" name="wp_custom_attachment" value="" size="25">';
    echo $html;

add_action('save_post', 'save_custom_meta_data');
function save_custom_meta_data($id) {
    if(!empty($_FILES['wp_custom_attachment']['name'])) {
        $supported_types = array('application/pdf');
        $arr_file_type = wp_check_filetype(basename($_FILES['wp_custom_attachment']['name']));
        $uploaded_type = $arr_file_type['type'];

        if(in_array($uploaded_type, $supported_types)) {
            $upload = wp_upload_bits($_FILES['wp_custom_attachment']['name'], null, file_get_contents($_FILES['wp_custom_attachment']['tmp_name']));
            if(isset($upload['error']) && $upload['error'] != 0) {
                wp_die('There was an error uploading your file. The error is: ' . $upload['error']);
            } else {
                update_post_meta($id, 'wp_custom_attachment', $upload);
        else {
            wp_die("The file type that you've uploaded is not a PDF.");

function update_edit_form() {
    echo ' enctype="multipart/form-data"';
add_action('post_edit_form_tag', 'update_edit_form');

To get the PDF

$hotel_brochure = get_post_meta( $post_id, 'wp_custom_attachment', true );
  • It works. There was this line missing though: add_post_meta($id, 'wp_custom_attachment', $upload); above this one: update_post_meta($id, 'wp_custom_attachment', $upload); Thank you
    – belacqua16
    Jun 21 '13 at 9:57
  • 1
    Thank you Kuljeet Singh for this solution it is workin perfectly (with the remark of belacqua). I have please one question: How to make this solution store the uploaded file information. Actually when you update the post, the custom box asks you to upload a file but doesnt indicate that there is an existing uploaded file. Thanks in advance Jul 18 '13 at 23:03
  • Worpdress 5.6 here. I tried without add_post_meta and it works. Be careful though, althought this code overwrites the previously updated meta data as expected, it does NOT overwrites the previously uploaded file since wp_upload_bits uses a different name (something like file-1.pdf, file-2.pdf, file-3.pdf, and so on). Check the wp-content/upload folder.
    – leaf
    Dec 9 '20 at 13:20
  • Also note that PHP 7 evaluates $upload['error'] != 0 to false when $upload['error'] contains a message (of type string). It's no longer the case with PHP 8, but still you should use strict type checking (===) in order to avoid unpredictable behaviours (btw $upload['error'] can be a string or false).
    – leaf
    Dec 9 '20 at 14:22
  • A final word, cite your sources: code.tutsplus.com/articles/… :-P Some extra stuffs concerning my two comments above: wordpress.stackexchange.com/a/379569/198773.
    – leaf
    Dec 9 '20 at 15:33

I just got this working last night using the above code (and the extra comment) and there are a few things I'd like to add here. First, in the "To get the PDF" section, 'wpcf-brochure' should be changed to 'wp_custom_attachment'. Next, to answer the final question from OP, to make it appear in the back end, here's the technique I used. Before the line that says "echo $html;" in functions.php, add:

$filearray = get_post_meta( get_the_ID(), 'wp_custom_attachment', true );
$this_file = $filearray['url'];
if($this_file != ""){
   $html .= '<div>Current file:<br>"' . $this_file . '"</div>';

Here is a little boost for the one who wants to fix and fix the accepted answer:

define('PREFIX', 'a-good-prefix-');
echo '<input type="file" name="' . PREFIX . 'attachment">';
add_action('save_post', function ($post_id) {
  $key = PREFIX . 'attachment';
  if (empty($_FILES[$key]['name'])) return;
  if (metadata_exists('post', $post_id, $key)) {
    unlink(get_post_meta($post_id, $key, true)['file']);
  $name = $_FILES[$key]['name'];
  $tmp = $_FILES[$key]['tmp_name'];
  $bits = file_get_contents($tmp);
  $upload = wp_upload_bits($name, null, $bits);
  if (isset($upload['error']) && $upload['error'] !== false) {
    wp_die('Upload error: ' . $upload['error']);
  } else {
    update_post_meta($post_id, $key, $upload);

Actual sources: https://code.tutsplus.com/articles/attaching-files-to-your-posts-using-wordpress-custom-meta-boxes-part-1--wp-22291.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.