I am trying to allow CSV files in a dashboard menu page like this..

<form method="post" enctype="multipart/form-data">
    <input type="file" name="csv_file" id="csv_file"  multiple="false" accept=".csv" />
    <input type="submit" value="Upload" />

require_once( ABSPATH . 'wp-admin/includes/file.php' );
require_once( ABSPATH . 'wp-admin/includes/media.php' );

$attachment_id = media_handle_upload ( 'csv_file', 0, array(), array(
    'test_form' => false,
    'mimes'     => array(
        'csv'   => 'text/csv',
) );

When I upload a CSV file to the form I get the following error message...

Sorry, this file type is not permitted for security reasons.

Can anyone spot what I am doing wrong? I had assumed I had allowed the CSV mime type in the above code.


There's a bug in WordPress 4.7-4.7.3 related to validating MIME types, so the code provided by Dave Romsey won't work.

There's a plugin in the repo that will bypass MIME checks, but it disables the checks for all users and all extensions. I think a better way would be to add a new capability for administrators that will allow them to upload .csv extensions.

//* Register activation and deactivation hooks
register_activation_hook( __FILE__ , 'wpse_258192_activation' );
register_deactivation_hook( __FILE__ , 'wpse_258192_deactivation' );

//* Add upload_csv capability to administrator role
function wpse_258192_activation() {
  $admin = get_role( 'administrator' );
  $admin->add_cap( 'upload_csv' );

//* Remove upload_csv capability from administrator role
function wpse_258192_deactivation() {
  $admin = get_role( 'administrator' );
  $admin->remove_cap( 'upload_csv' );

//* Add filter to check filetype and extension
add_filter( 'wp_check_filetype_and_ext', 'wpse_258192_check_filetype_and_ext', 10, 4 );

//* If the current user can upload_csv and the file extension is csv, override arguments - edit - "$pathinfo" changed to "pathinfo"
function wpse_258192_check_filetype_and_ext( $args, $file, $filename, $mimes ) {
  if( current_user_can( 'upload_csv' ) && 'csv' === pathinfo( $filename )[ 'extension' ] ){
    $args = array(
      'ext'             => 'csv',
      'type'            => 'text/csv',
      'proper_filename' => $filename,
  return $args;
| improve this answer | |

By default, WordPress blocks .csv file uploads. The mime_types filter will allow you to add .csv files or any other file to be uploaded:

add_filter( 'mime_types', 'wpse_mime_types' );
function wpse_mime_types( $existing_mimes ) {
    // Add csv to the list of allowed mime types
    $existing_mimes['csv'] = 'text/csv';

    return $existing_mimes;
| improve this answer | |
  • So with that being the case, what is the mime override of media_handle_upload used for? – fightstarr20 Feb 27 '17 at 22:59
  • 1
    Actually, the $mimes array within the $overrides array does serve the same purpose after all. So the issue may stem from the bug noted by Nathan Johnson in his answer. (I had some code enabled in my testing environment that overrode the mime check because of the bug, which I had forgotten about :) – Dave Romsey Feb 27 '17 at 23:53

If you want a temporary quick and easy solution you can allow unfiltered uploads in your wp-config.php .


This line should probably not stay in your config.php, but if you want to do something like a woocommerce products import via CSV only once, it can be an easy fix.

| improve this answer | |

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.