pre_move_uploaded_file
云策文档标注
概述
pre_move_uploaded_file 是一个 WordPress 过滤器,用于在文件上传通过所有检查后,决定是否跳过移动文件的操作。如果过滤器返回非 null 值,将完全跳过文件移动和相关错误报告。
关键要点
- 过滤器允许开发者自定义文件上传后的处理逻辑,例如复制文件而非移动。
- 参数包括 $move_new_file(控制是否移动文件)、$file(引用 $_FILES 数组元素)、$new_file(新文件名)和 $type(新文件 MIME 类型)。
- 常用于 _wp_handle_upload() 函数中,影响 wp_handle_sideload() 和 media_handle_sideload() 等上传处理流程。
代码示例
add_filter( 'pre_move_uploaded_file', function( $move, $file, $new_file ) {
// 复制文件而非移动
$move = @copy( $file['tmp_name'], $new_file );
if ( false === $move && WP_DEBUG ) {
trigger_error( ... ); // 错误处理
}
return $move; // 返回 true/false 以跳过默认移动
}, 10, 3 );注意事项
- 使用此过滤器时,需确保文件路径已通过 WordPress 验证,避免安全风险。
- 示例代码仅复制文件到上传目录,不自动创建媒体附件或关联到文章,需额外处理。
- 过滤器从 WordPress 4.9.0 版本引入,适用于高级上传场景定制。
原文内容
Filters whether to short-circuit moving the uploaded file after passing all checks.
Description
If a non-null value is returned from the filter, moving the file and any related error reporting will be completely skipped.
Parameters
$move_new_filemixed-
If null (default) move the file after the upload.
$filearray-
Reference to a single element from
$_FILES.namestringThe original name of the file on the client machine.typestringThe mime type of the file, if the browser provided this information.tmp_namestringThe temporary filename of the file in which the uploaded file was stored on the server.sizeintThe size, in bytes, of the uploaded file.errorintThe error code associated with this file upload.
$new_filestring-
Filename of the newly-uploaded file.
$typestring-
Mime type of the newly-uploaded file.
Source
$move_new_file = apply_filters( 'pre_move_uploaded_file', null, $file, $new_file, $type );
Changelog
| Version | Description |
|---|---|
| 4.9.0 | Introduced. |
Skip to note 2 content
Aurovrata Venet
There is an interesting question on this filter in the support forum with a rather complicated reply, however, I have to use this for a slightly different problem.
I normally use the function
media_handle_sideload()to move a file into the wp uploads fodler and save it as a media attachment post, which works quite nicely.However, recently I had to copy a file (rather than move it), in my plugin extension as the original plugin still needed to have access to the original file location (a temporary folder on the fs), and unfortunately there is no way to get the
media_handle_sideload()to copy rather than move a file.This is where this filter comes in handy. The
media_handle_sideload()makes use of thewp_handle_sideload(), which in turns calls the_wp_handle_upload()function, within which thepre_move_uploaded_filefilter is applied.The filter can be used to switch off the actual moving of the file while retaining all the goodness of validation that the function handles, allowing one to handle the actual file handling, copying it instead of moving it in my case. This is how I used it,
// first step is to identify the filename and path you want to copy. $file_arr = array( 'name' => $filename, //something like my-photo.jpg 'tmp_name' => $path, //something like /..../wp-content/uploads/cf7-uploads/tmp/my-photo.jpg ); // next use a unique action handle to identify your file process from others handled by WP core/plugins. $action = 'wpdocs_file_copy'; // this allows to identify your file action with the filter applied at the start of _wp_handle_upload(). // register your file handling process with an anonymous function. add_filter( "{$action}_prefilter", function( $file ) { // next we hook the filter to cancel the file move. add_filter( 'pre_move_uploaded_file', function( $move, $file, $new_file ) { // now you copy your file, knowing that the $new_file path has been validated by WP. $move = @copy( $file['tmp_name'], $new_file ); if ( false === $move && WP_DEBUG ) { trigger_error( ... ); // handle the error (optional). } return $move; // either false or true, but not null will cancel the file move. }, 10, 3 ); // pre_move filter return $file; } ); // filter // now you fire the actually file moving process which will validate the new location of the file on the fs and trigger the above filter. $new_file_arr = wp_handle_sideload( $file_arr, array( 'action' => $action, // the action defined above. 'test_form' => false, // in this case the file I am copying is not coming from the $_FILES submission and so I don't need the extra validation. ), current_time( 'mysql' ) // timestamp. ); if ( isset( $new_file_arr['error'] ) ) { //in case there was an error. // handle the error (optional) } else { $url = $new_file_arr['url']; $type = $new_file_arr['type']; $new_file = $new_file_arr['file']; } // you can then go on to create an attachment post and link it to a parent post if need be.Note, the above only copies the file to the
wp-content/uploads/<year>/<month>/folder structure, but does not actually create an attachment post (required to see your file in the Media section of the dashboard), nor links it to a parent post (eg as a featured/thumbnail image). If you need to see how to do this I suggest you take a look at the process used in themedia_handle_sideload()function.