在WordPress插件中启用AJAX文件上传

tech2022-10-21  105

Providing upload functionality in our plugin is always tricky business. We need to be able to provide a good user experience (UX) for uploading, while also keeping an eye on the security concerns that come with it. If it’s not done properly, we could potentially put the site at risk for any security vulnerabilities that arise.

在我们的插件中提供上传功能始终是一件棘手的事情。 我们需要能够为上传提供良好的用户体验(UX),同时还要注意随之而来的安全性问题。 如果处理不当,我们有可能使站点面临任何出现的安全漏洞的风险。

Instead of building the whole solution from scratch, we can leverage the WordPress core code to our advantage to speed up the development, specifically utilising async-upload.php file that’s located in the wp-admin directory.

无需从头开始构建整个解决方案,我们可以利用WordPress核心代码来加快开发速度,特别是利用wp-admin目录中的async-upload.php文件。

Using the async-upload.php file has several advantages. Firstly, since it’s used by WordPress core itself for async uploading in the media library, we can be assured that the code is up to standard. Plus, all the validation and privilege checking has been done so we don’t need to do that ourselves.

使用async-upload.php文件具有多个优点。 首先,由于WordPress核心本身已将其用于媒体库中的异步上传,因此我们可以确保代码符合标准。 另外,所有验证和特权检查都已经完成,因此我们不需要自己做。

要求 (Requirements)

There are several rules that need to be followed if we’re to utilise this script. Here’s a breakdown to each of them.

如果要使用此脚本,需要遵循几个规则。 这是每个人的细分。

The file input that is used must has its name attribute set to async-upload

使用的file输入必须将其name属性设置为async-upload

This is due to the fact that once the validation is passed inside the async-upload.php file, wp_ajax_upload_attachment which then further calls the media_handle_upload function that uses async-upload as the first arguments. Using any other value will not work.

这是由于以下事实:一旦在async-upload.php文件中传递了验证, wp_ajax_upload_attachment进一步调用media_handle_upload函数,该函数使用async-upload作为第一个参数。 使用任何其他值将不起作用。

The nonce that we sent alongside the AJAX request must use the default _wpnonce key with the value generated from the wp_create_nonce('media-form') function

我们与AJAX请求一起发送的随机数必须使用默认的_wpnonce密钥以及wp_create_nonce('media-form')函数生成的值

This is due to the validation in the form of check_ajax_referer that is happening inside the wp_ajax_upload_attachment function.

这是由于在形式验证check_ajax_referer是在内部发生wp_ajax_upload_attachment功能。

The data sent via the AJAX request also needs to have a key called action with a value of upload-attachment

通过AJAX请求发送的数据还需要有一个名为action的键,其值为上upload-attachment

This is validated inside the async-upload.php file which will only trigger the wp_ajax_upload_attachment function when the value is set correctly.

这在async-upload.php文件中进行了验证,该文件仅在正确设置该值时才会触发wp_ajax_upload_attachment函数。

关于插件 (About the Plugin)

To better illustrate the idea of building custom AJAX file upload functionality into a plugin, we will create a simple plugin to test it out.

为了更好地说明将自定义AJAX文件上传功能构建到插件中的想法,我们将创建一个简单的插件对其进行测试。

For the purpose of this tutorial, we’re going to create a plugin that allows registered users to submit an image for some sort of contest. We will have a frontend submission form, which means that the upload form will be displayed on a certain page where the user can directly upload the image. This is a perfect candidate to implement AJAX uploading functionality.

就本教程而言,我们将创建一个插件,允许注册用户提交某种比赛的图像。 我们将有一个前端提交表单,这意味着上载表单将显示在用户可以直接上载图像的特定页面上。 这是实现AJAX上传功能的理想之选。

Since we’re trying to keep things simple, let’s define some guidelines of what this plugin will and will not do, for the sake of the length of this tutorial.

由于我们试图使事情保持简单,因此,为了本教程的长度,让我们定义一些有关此插件将要做什么和不做什么的准则。

The plugin will be able to:

该插件将能够:

Allow the admin to attach the form to any page via a shortcode.

允许管理员通过简码将表单附加到任何页面。 Show the registered users a submission form with AJAX upload functionality.

向注册用户显示具有AJAX上传功能的提交表单。 Send an email to notify the site admin upon submission.

发送电子邮件以在提交后通知站点管理员。

For the scope of this tutorial, the plugin will not:

在本教程的范围内,该插件不会:

Store any submissions into the database.

将所有提交内容存储到数据库中。 View the submissions in the backend.

在后端查看提交的内容。 Allow anonymous users to upload the files.

允许匿名用户上传文件。

引导插件 (Bootstrapping the Plugin)

Head to the wp-content/plugins folder and create a new folder where all of our plugin codes will reside. I will use the name sitepoint-upload for the rest of this tutorial, with prefix of su_ to all functions and hooks callbacks.

转到wp-content/plugins文件夹并创建一个新文件夹,所有我们的插件代码都将驻留在该文件夹中。 在本教程的其余部分中,我将使用名称sitepoint-upload ,所有功能均带有su_前缀,并挂钩回调。

Next, create the main plugin file, with the same name as the folder, to make things easier. Inside the plugin folder, we will also have a js folder which contains an empty script.js file for now.

接下来,使用与文件夹相同的名称创建主插件文件,以使事情变得容易。 在plugin文件夹中,我们还将有一个js文件夹,其中现在包含一个空的script.js文件。

Here’s an updated directory structure for our plugin.

这是我们插件的更新目录结构。

wp-content/ |-- plugins/ |-- sitepoint-upload/ |-- js/ | |-- script.js |--sitepoint-upload.php

Let’s put in a simple plugin header into the plugin main file, sitepoint-upload.php, then go ahead to the plugins page to activate it. Here’s example of mine:

让我们在插件主文件sitepoint-upload.php放入一个简单的插件头,然后转到插件页面将其激活。 这是我的示例:

<?php /* Plugin Name: Simple Uploader Plugin URI: https://www.sitepoint.com Description: Simple plugin to demonstrate AJAX upload with WordPress Version: 0.1.0 Author: Firdaus Zahari Author URI: https://www.sitepoint.com/author/fzahari/ */

排队脚本 (Enqueue the Script)

We then can enqueue the empty script.js to the frontend, which will be used to handle our AJAX uploading functionality, as well as enhancing the submission form.

然后,我们可以将空的script.js排队到前端,该前端将用于处理AJAX上载功能以及增强提交表单。

function su_load_scripts() { wp_enqueue_script('image-form-js', plugin_dir_url( __FILE__ ) . 'js/script.js', array('jquery'), '0.1.0', true); } add_action('wp_enqueue_scripts', 'su_load_scripts');

We’re also going to localize some data which will be used inside script.js using the function wp_localize_script. We need three things, a correct URL to both admin-ajax.php since we’re going to submit the form via AJAX as well, and also the URL to the async-upload.php file. The third item we need to localize is the nonce, which will be generated using the wp_create_nonce function.

我们还将使用wp_localize_script函数本地化将在script.js使用的一些数据。 我们需要三件事,一个正确的admin-ajax.php URL,因为我们也将通过AJAX提交表单,还需要一个async-upload.php文件的URL。 我们需要本地化的第三项是随机数,它将使用wp_create_nonce函数生成。

The updated callback function for our wp_enqueue_scripts hook looks like the this:

wp_enqueue_scripts挂钩的更新后的回调函数如下所示:

function su_load_scripts() { wp_enqueue_script('image-form-js', plugin_dir_url( __FILE__ ) . 'js/script.js', array('jquery'), '0.1.0', true); $data = array( 'upload_url' => admin_url('async-upload.php'), 'ajax_url' => admin_url('admin-ajax.php'), 'nonce' => wp_create_nonce('media-form') ); wp_localize_script( 'image-form-js', 'su_config', $data ); } add_action('wp_enqueue_scripts', 'su_load_scripts');

注册提交表单的简码 (Register the Shortcode for a Submission Form)

We will then need to register the shortcode for our submission form, so that we can easily put it in any pages we want instead of writing the same markup over and over again. Our form will have:

然后,我们将需要为提交表单注册简码,以便我们可以轻松地将其放入所需的任何页面中,而不必一遍又一遍地编写相同的标记。 我们的表格将包含:

A text input field for user’s name

用户名的文本输入字段 Another email input field for user’s email address

用户电子邮件地址的另一个电子邮件输入字段

The async-upload file input for AJAX uploading

用于AJAX上传的async-upload文件输入

A bunch of placeholder div that will be used for email preview, error messages and other items.

一堆占位符div ,将用于电子邮件预览,错误消息和其他项目。

We will also be disabling the submission form entirely if the user is not currently logged in, and display a login link instead.

如果用户当前尚未登录,我们还将完全禁用提交表单,而是显示一个登录链接。

function su_image_form_html(){ ob_start(); ?> <?php if ( is_user_logged_in() ): ?> <p class="form-notice"></p> <form action="" method="post" class="image-form"> <?php wp_nonce_field('image-submission'); ?> <p><input type="text" name="user_name" placeholder="Your Name" required></p> <p><input type="email" name="user_email" placeholder="Your Email Address" required></p> <p class="image-notice"></p> <p><input type="file" name="async-upload" class="image-file" accept="image/*" required></p> <input type="hidden" name="image_id"> <input type="hidden" name="action" value="image_submission"> <div class="image-preview"></div> <hr> <p><input type="submit" value="Submit"></p> </form> <?php else: ?> <p>Please <a href="<?php echo esc_url( wp_login_url( get_permalink() ) ); ?>">login</a> first to submit your image.</p> <?php endif; ?> <?php $output = ob_get_clean(); return $output; } add_shortcode('image_form', 'su_image_form_html');

A few explanations about the shortcode callback function above:

有关上述shortcode回调函数的一些解释:

The shortcode we register is image_form.

我们注册的简码是image_form 。

We’re using output buffering so that we can be more flexible with what we expose inside the shortcode callback function.

我们正在使用输出缓冲,以便我们可以更灵活地利用shortcode回调函数中公开的内容。

We’re also restricting file selection for images only via the accept attribute on the file input. Note that this doesn’t replace the actual file validation. (More info)

我们还仅通过文件输入上的accept属性来限制图像的文件选择。 请注意,这并不能代替实际的文件验证。 (更多信息)

For the login URL, we supply the current page permalink into the wp_login_url so that the user will be redirected back to our submission page upon successful login.

对于登录URL,我们将当前页面永久链接提供到wp_login_url以便在成功登录后将用户重定向到我们的提交页面。

将upload_files功能添加到特定用户角色 (Add upload_files Capability to the Specific User Roles)

To make sure our plugin is functioning properly, we need to alter the capability of role of subscriber because by default, users with the role subscriber don’t have the capability to upload files.

为确保我们的插件正常运行,我们需要更改subscriber角色的功能,因为默认情况下,具有subscriber角色的subscriber不具有上传文件的能力。

function su_allow_subscriber_to_uploads() { $subscriber = get_role('subscriber'); if ( ! $subscriber->has_cap('upload_files') ) { $subscriber->add_cap('upload_files'); } } add_action('admin_init', 'su_allow_subscriber_to_uploads');

Note, the subscriber role will only be modified if it still doesn’t have upload_files capability.

请注意,仅当subscriber角色仍然不具有upload_files功能时,才会对其进行修改。

Now that we’re finished with our plugin basics, let’s create a new page that will display our submission form.

现在我们已经完成了插件基础知识,让我们创建一个新页面来显示我们的提交表单。

This is how the form looks on the frontend, on a default WordPress installation with twentysixteen theme active.

这是表单在前端上的外观,在默认的WordPress安装中, twentysixteen主题处于活动状态。

If we’re logged out of the site, the notice will be shown instead.

如果我们退出网站,则会显示该通知。

Looks like our plugin comes together nicely!

看起来我们的插件很好地结合在一起!

实施AJAX上传 (Implementing the AJAX Upload)

Now that our base plugin has been configured correctly, we can focus on the core functionality that we need to do, the AJAX upload.

现在我们的基本插件已正确配置,我们可以专注于我们需要做的核心功能,即AJAX上传。

Let’s open up our script.js file that is located inside the js folder to proceed. We will first wrap the whole code within immediately-invoked function expression (IIFE).

让我们打开位于js文件夹内的script.js文件继续。 我们首先将整个代码包装在立即调用的函数表达式(IIFE)中 。

Next, we will cache a few selectors to speed up our code. This includes the references to the image preview div, the input file, as well as the div used to display the upload notice.

接下来,我们将缓存一些选择器以加速我们的代码。 这包括对图像预览div ,输入文件以及用于显示上传通知的div引用。

(function($) { $(document).ready(function() { var $formNotice = $('.form-notice'); var $imgForm = $('.image-form'); var $imgNotice = $imgForm.find('.image-notice'); var $imgPreview = $imgForm.find('.image-preview'); var $imgFile = $imgForm.find('.image-file'); var $imgId = $imgForm.find('[name="image_id"]'); }); })(jQuery);

The cached selectors will be useful to us in the long run. As mentioned before, there are few rules that need to be followed in order for the validation in the async-upload.php file to pass. To do that, we will make a POST request via AJAX to the async-upload.php file with the correct key or value pairs as specified. This can be done using the FormData API.

从长远来看,缓存的选择器对我们很有用。 如前所述,为了使async-upload.php文件中的验证通过,需要遵循一些规则。 为此,我们将使用指定的正确键或值对通过AJAX向async-upload.php文件发出POST请求。 这可以使用FormData API来完成。

We will first hook on the change event on the file input, and if the input is changed, only then we will trigger the AJAX upload.

我们将首先挂钩文件输入上的change事件,如果输入被更改,则只有这样我们才会触发AJAX上传。

$imgFile.on('change', function(e) { e.preventDefault(); var formData = new FormData(); formData.append('action', 'upload-attachment'); formData.append('async-upload', $imgFile[0].files[0]); formData.append('name', $imgFile[0].files[0].name); formData.append('_wpnonce', su_config.nonce); $.ajax({ url: su_config.upload_url, data: formData, processData: false, contentType: false, dataType: 'json', type: 'POST', success: function(resp) { console.log(resp); } }); });

For now, let’s leave the code as above, and test the upload functionality to make sure we’re on the right track. Using the developer console (depending on what browser is used), check the console tab for the output. A sample of response given by async-upload.php file upon successful upload as follows:

现在,让我们保留上面的代码,并测试上传功能,以确保我们处在正确的轨道上。 使用开发者控制台(取决于所使用的浏览器),检查控制台选项卡的输出。 成功上传后, async-upload.php文件给出的响应示例如下:

We can also check for the file existence by going directly to the wp-content/uploads directory. Now that we see that the uploading functionality is working well, let’s work on a few improvements to our upload script. Here are some improvements that I can think of:

我们还可以通过直接转到wp-content/uploads目录来检查文件是否存在。 现在,我们看到上传功能运行良好,让我们对上传脚本进行一些改进。 我可以想到以下一些改进:

Show a progress bar or text during the upload process.

在上传过程中显示进度条或文本。 Show the uploaded image preview on successful upload.

成功上传后显示上传的图片预览。 Display error if the upload failed.

如果上传失败,则显示错误。 Provide a way for user to upload a new image to replace the current one.

为用户提供一种上传新图像来替换当前图像的方法。

Let’s see how to do this one by one.

让我们来看看如何一一完成。

在上传过程中显示进度栏或文本 (Show a Progress Bar or Text During the Upload Process)

This is actually a simple one. We only need to define a callback for the beforeSend of jQuery AJAX. Somewhere in the code for the AJAX upload, put the code block as follows:

这实际上很简单。 我们只需要为jQuery AJAX的beforeSend定义一个回调。 在用于AJAX上传的代码中的某处,将代码块如下所示:

beforeSend: function() { $imgFile.hide(); $imgNotice.html('Uploading&hellip;').show(); },

We use the empty div with the class image-notice defined previously to show the progress text to the user. We’re also hiding the file input during the upload process.

我们使用空div和先前定义的类image-notice来向用户显示进度文本。 在上传过程中,我们还将隐藏文件输入。

For the supported browsers, we can even show the upload percentage. What we can do is to override the original jQuery xhr object with our own. Add this to the $.ajax configuration:

对于受支持的浏览器,我们甚至可以显示上传百分比。 我们可以做的是用我们自己的对象覆盖原始的jQuery xhr对象。 将此添加到$.ajax配置中:

xhr: function() { var myXhr = $.ajaxSettings.xhr(); if ( myXhr.upload ) { myXhr.upload.addEventListener( 'progress', function(e) { if ( e.lengthComputable ) { var perc = ( e.loaded / e.total ) * 100; perc = perc.toFixed(2); $imgNotice.html('Uploading&hellip;(' + perc + '%)'); } }, false ); } return myXhr; }

What this code does for supported browsers, is simply appending the upload percentage after the Uploading text, which is a rather nice enhancement. For unsupported browsers, nothing will happen which is a nice graceful degradation.

这段代码对受支持的浏览器的作用是,只需在“ Uploading文本之后附加上载百分比,这是一个相当不错的增强。 对于不受支持的浏览器,将不会发生任何事情,这是一个很好的优雅降级。

成功上传时显示上传的图像预览,或者上传失败时显示错误 (Show the Uploaded Image Preview on Successful Upload or Display Error When the Upload Failed)

Depending on the response we get from the async-upload.php script, we will show a different message to the user. If the success key is set to true, we can then show the uploaded image to the user, and hide the file input. If the upload fails, we will replace the text inside the div with image-notice previously.

根据从async-upload.php脚本获得的响应,我们将向用户显示不同的消息。 如果success密钥设置为true ,那么我们可以向用户显示上传的图像,并隐藏文件输入。 如果上传失败,我们之前会用image-notice替换div的文本。

success: function(resp) { if ( resp.success ) { $imgNotice.html('Successfully uploaded.'); var img = $('<img>', { src: resp.data.url }); $imgId.val( resp.data.id ); $imgPreview.html( img ).show(); } else { $imgNotice.html('Fail to upload image. Please try again.'); $imgFile.show(); $imgId.val(''); } }

$imgId is a hidden input that we’re using to reference the uploaded image ID. We’re going to use this value later for the form submission, so don’t worry about it yet.

$imgId是一个隐藏的输入,我们将用来引用上载的图像ID。 稍后我们将使用此值进行表单提交,因此不必担心。

为用户提供一种上传新图像以替换当前图像的方式 (Provide a Way for User to Upload a New Image to Replace the Current One)

What we’re going to do is to provide a link as a method for the user to replace the currently uploaded image with a new one. We will change the notice shown when the upload succeeds from:

我们要做的是提供一个链接,以供用户用新的图像替换当前上传的图像。 上传成功后,我们将更改显示的通知:

$imgNotice.html('Successfully uploaded.');

to

$imgNotice.html('Successfully uploaded. <a href="#" class="btn-change-image">Change?</a>');

Now that we have an anchor with a class of btn-change-image, we will use that to our advantage. We can then add a click event listener on that anchor, when it’s clicked, it will remove the current image preview. We will also hide the notice message, as well as display the file input again with its value which has been reset.

现在我们有了一个带有btn-change-image类的锚,我们将利用它来发挥我们的优势。 然后,我们可以在该锚点上添加一个click事件侦听器,当单击它时,它将删除当前图像预览。 我们还将隐藏通知消息,并再次显示输入的文件及其已重置的值。

$imgForm.on( 'click', '.btn-change-image', function(e) { e.preventDefault(); $imgNotice.empty().hide(); $imgFile.val('').show(); $imgId.val(''); $imgPreview.empty().hide(); });

We also need to reset the file input value when it’s clicked, so that the change event can be triggered again.

单击文件输入值时,我们还需要重置它,以便可以再次触发change事件。

$imgFile.on('click', function() { $(this).val(''); $imgId.val(''); });

Before we proceed to the next section, let’s run through the uploading functionality once again and see if everything works as intended.

在继续下一节之前,让我们再次浏览上传功能,看看一切是否按预期进行。

完成插件 (Completing the Plugin)

We’re going to handle the form submission via AJAX, so we’re binding an event listener to the submit event of that form.

我们将通过AJAX处理表单提交,因此我们将事件侦听器绑定到该表单的submit事件。

$imgForm.on('submit', function(e) { e.preventDefault(); var data = $(this).serialize(); $.post( su_config.ajax_url, data, function(resp) { if ( resp.success ) { $formNotice.css('color', 'green'); $imgForm[0].reset(); $imgNotice.empty().hide(); $imgPreview.empty().hide(); $imgId.val(''); $imgFile.val('').show(); } else { $formNotice.css('color', 'red'); } $formNotice.html( resp.data.msg ); }); });

Based on the above code, we’re going to process the submission on the backend using the built-in WordPress AJAX action. Upon successful submission, we’re going to reset the form, remove the image preview, as well as set the form notice text to green.

基于以上代码,我们将使用内置的WordPress AJAX action在后端处理提交。 成功提交后,我们将重置表单,删除图像预览,并将表单通知文本设置为绿色。

For a failed submission, we simply set the form notice text colour to red. This will allow the user to review the form data, before retrying again.

对于失败的提交,我们只需将表单通知文本颜色设置为红色。 这将允许用户在重试之前查看表单数据。

Now, open up the plugin main file again to add the AJAX callback. Since we’re setting the action value to image_submission, we will need to add a valid callback to the wp_ajax_image_submission action.

现在,再次打开插件主文件以添加AJAX回调。 由于我们将action值设置为image_submission ,因此我们需要向wp_ajax_image_submission动作添加有效的回调。

add_action('wp_ajax_image_submission', 'su_image_submission_cb');

In the callback function, there are a few things that need to be done first. We need to check for a valid AJAX nonce, as well as validating the user inputs. For the scope of this tutorial, we’re going to simply email the site admin for any new submission.

在回调函数中,首先需要完成一些事情。 我们需要检查有效的AJAX随机数,以及验证用户输入。 在本教程的范围内,我们将简单地通过电子邮件向网站管理员发送任何新提交的内容。

Here’s the full code for the AJAX callback function:

这是AJAX回调函数的完整代码:

function su_image_submission_cb() { check_ajax_referer('image-submission'); $user_name = filter_var( $_POST['user_name'],FILTER_SANITIZE_STRING ); $user_email = filter_var( $_POST['user_email'], FILTER_VALIDATE_EMAIL ); $image_id = filter_var( $_POST['image_id'], FILTER_VALIDATE_INT ); if ( ! ( $user_name && $user_email && $image_id ) ) { wp_send_json_error( array('msg' => 'Validation failed. Please try again later.') ); } $to = get_option('admin_email'); $subject = 'New image submission!'; $message = sprintf( 'New image submission from %s (%s). Link: %s', $user_name, $user_email, wp_get_attachment_url( $image_id ) ); $result = wp_mail( $to, $subject, $message ); if ( $result ) { wp_send_json_error( array('msg' => 'Email failed to send. Please try again later.') ); } else { wp_send_json_success( array('msg' => 'Your submission successfully sent.') ); } }

For our purpose, a simple check_ajax_referer check and native filter_var PHP function is suffice for our use case. We’re also going to utilise the wp_send_json_error and wp_send_json_success function to send back the response.

就我们的目的而言,一个简单的check_ajax_referer检查和本机filter_var PHP函数就足够了。 我们还将利用wp_send_json_error和wp_send_json_success函数发送回响应。

With that, our plugin is finished and fully functional. To verify, try completing the form properly and see if the email is received with the link to the uploaded image.

这样,我们的插件就完成了并且功能齐全。 要进行验证,请尝试正确填写表单,然后查看是否收到了带有上载图像链接的电子邮件。

进一步改进 (Further Improvements)

Since the objective of this tutorial is to demonstrate how to do AJAX uploading via the internal async-upload.php file, we’re definitely cutting things short in a few places. Here are some suggestions that can improve our simple plugin overall.

由于本教程的目的是演示如何通过内部async-upload.php文件进行AJAX上传,因此我们肯定会在一些地方async-upload.php一些工作。 这里有一些建议,可以从整体上改善我们的简单插件。

Adding more fields to the form to capture any additional value for submission.

在表单中添加更多字段以捕获提交的任何其他值。 Enqueue a separate CSS file to better style the form, notice and upload progress.

排队一个单独CSS文件,以更好地样式化表单,注意和上传进度。 Save the submitted data into the database, so that we can review it back again.

将提交的数据保存到数据库中,以便我们可以再次查看它。 Doing more validation to the upload process so that it can be more secure.

对上传过程进行更多验证,以使其更加安全。

The full source code of the plugin is available on GitHub.

该插件的完整源代码可在GitHub上找到 。

结论 (Conclusion)

As a conclusion, implementing AJAX upload in a plugin can be sped up if we know where to look. By using the async-upload.php file, we can reduce the development time to implement the feature, as well as gaining some confidence since the same file is used by WordPress core to process the user upload in the administration dashboard.

结论是,如果我们知道从哪里看,则可以加快在插件中实现AJAX上传的速度。 通过使用async-upload.php文件,我们可以减少开发时间来实现该功能,并获得一定的信心,因为WordPress核心使用同一文件来处理管理仪表板中的用户上传。

翻译自: https://www.sitepoint.com/enabling-ajax-file-uploads-in-your-wordpress-plugin/

最新回复(0)