Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

I'm using the Media Library on the front end of my website and I'd like to stop users from being able to spam my server by uploading an unlimited number of files.

As such, I'd like to do one or maybe all of the below:

  1. Give users a maximum upload capacity; i.e. users can upload up to 10 megabytes of files.
  2. Limit the number of files a user can upload on a per-post basis
  3. Limit the number of files a user can upload when they click the "Insert" button, i.e. the Flash uploader and Classic uploader will only let you upload, for instance, 2 files at a time.

None of these are bullet-proof but they'd hopefully make such "spamming" a difficulty.

Thanks in advance,

share|improve this question

2 Answers 2

up vote 8 down vote accepted

Assuming that you're providing upload functionality via WordPress' native functions, lik wp_handle_upload or something more high-level, we come to the conclusion that several hooks are going to be pulled.

http://core.trac.wordpress.org/browser/tags/3.3/wp-admin/includes/file.php#L212

The wp_handle_upload function would probably be the last native function to touch the file, and would know all the information that is necessary to keep track of.

Two hooks inside this function are of interest: wp_handle_upload and wp_handle_upload_prefilter. The latter comes first, this could check against the current limits and prevent the file from being uploaded. The former would track filesizes and count. Storing the information would be handled by none other than update_user_meta.

add_filter( 'wp_handle_upload', 'wpse47580_update_upload_stats' );
function wpse47580_update_upload_stats( $args ) {
    $file = $args['file'];
    $size = filesize( $file ); // bytes

    $user_id = get_current_user_id();

    $upload_count = get_user_meta( $user_id, 'upload_count', $single = true );
    $upload_bytes = get_user_meta( $user_id, 'upload_bytes', $single = true );

    update_user_meta( $user_id, 'upload_count', $upload_count + 1 );
    update_user_meta( $user_id, 'upload_bytes', $upload_bytes + $size );
}

add_filter( 'wp_handle_upload_prefilter', 'wpse47580_check_upload_limits' );
function wpse47580_check_upload_limits( $file ) {
    $user_id = get_current_user_id();

    $upload_count = get_user_meta( $user_id, 'upload_count', $single = true );
    $upload_bytes = get_user_meta( $user_id, 'upload_bytes', $single = true );

    $filesize = /* get filesize from $file array */;
    $upload_bytes_limit_reached = apply_filters( 'wpse47580_upload_bytes_limit_reached', 1024*1024*10 ) > ( $filesize + $upload_bytes );
    $upload_count_limit_reached = apply_filters( 'wpse47580_upload_count_limit_reached', 100 ) > ( $upload_count + 1 );

    if ( $upload_count_limit_reached || $upload_bytes_limit_reached )
        $file['error'] = 'Upload limit has been reached for this account!';

    return $file;
}

Theoretically, this works; practically - untested. Let us know how it goes.

Per post upload limits would be kept in the post meta, probably like {$user_id}_upload_count etc. Don't see why that wouldn't work.

If you're using custom code to handle uploads (which I doublt), then you can implement your own actions and filters just like wp_handle_uploads does.

share|improve this answer
    
Hi Soul - excellent post, thanks very much. I'm getting this working now. Could you explain what these lines do? $upload_bytes_limit_reached = apply_filters( 'wpse47580_upload_bytes_limit_reached', 1024*1024*10 ) > ( $filesize + $upload_bytes ); –  dunc Apr 2 '12 at 10:02
    
I've updated the code to change the lines I just mentioned, as they were causing me problems - I guess I'm missing a filter function but I'm not sure what I needed to do with it! I've posted my code as an answer, could you critique it? –  dunc Apr 2 '12 at 10:32
    
The apply_filters code would allow other plugins to hook into there, thought that would be useful. Could you describe the nature of the problems? –  soulseekah Apr 2 '12 at 11:41
1  
You must return $args in wp_handle_upload or the image will not be saved! –  skylarkcob 2 days ago

I've amended Soulseekah's code somewhat as the apply_filter variables weren't working for me - probably because I don't understand them!

# ==============================================================================================

# ==============================================================================================
# [File Upload]
#
# Two filters to give users a maximum upload limit of 10Mb and 100 files.
# This function runs after the file has been uploaded.

add_filter( 'wp_handle_upload', 'wpse47580_update_upload_stats' );
function wpse47580_update_upload_stats( $args ) {
    $size = filesize( $args['file'] );

    $user_id = get_current_user_id();

    $upload_count = get_user_meta( $user_id, 'upload_count', $single = true );
    $upload_bytes = get_user_meta( $user_id, 'upload_bytes', $single = true );

    update_user_meta( $user_id, 'upload_count', $upload_count + 1 );
    update_user_meta( $user_id, 'upload_bytes', $upload_bytes + $size );
}

# ==============================================================================================

# ==============================================================================================
# This function runs before the file is uploaded.

add_filter( 'wp_handle_upload_prefilter', 'wpse47580_check_upload_limits' );
function wpse47580_check_upload_limits( $file ) {
    $user_id = get_current_user_id();

    $upload_count = get_user_meta( $user_id, 'upload_count', $single = true );
    $upload_bytes = get_user_meta( $user_id, 'upload_bytes', $single = true );

    $filesize = $file['size']; // bytes

    if ( ( $filesize + $upload_bytes ) > ( 1024 * 1024 * 10 ) )
        $upload_bytes_limit_reached = true;
    else
        $upload_bytes_limit_reached = false;

    if ( ( $upload_count + 1 ) > 100 )
        $upload_count_limit_reached = true;
    else
        $upload_count_limit_reached = false;

    if ( $upload_count_limit_reached || $upload_bytes_limit_reached )
        $file['error'] = 'Upload limit has been reached for this account!';

    return $file;
}

This would be really simple to make a plugin from so I might release it at some point in the future, when I've developed an interface for it.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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