【问题标题】:Wordpress send form with multiple files to email without pluginWordpress 将包含多个文件的表单发送到没有插件的电子邮件
【发布时间】:2022-01-11 01:44:14
【问题描述】:

目的是允许用户将自己的新文章(文本和文件)材料发送到管理员的电子邮件。

有一种形式:

<form class="form form-send" enctype="multipart/form-data">
    <div class="send__inputs-block">
        <div class="sliding-label__block send__textarea-block">
            <textarea name="comment" id="comment" class="input textarea send__textarea" placeholder=" "></textarea>
            <label for="comment" class="text text--fz-18 sliding-label">
                <?php echo get_post_meta( get_the_ID(), 'joint_send_comment_text', true ); ?>
            </label>
        </div>
        <div class="sliding-label__block">
            <input id="name" type="text" name="name" class="input input-text" placeholder=" ">
            <label for="name" class="text text--fz-18 sliding-label">
                <?php echo get_post_meta( get_the_ID(), 'joint_send_name_text', true ); ?>
            </label>
        </div>
    </div>
    <div class="send__file-block">
        <input id="file" type="file" name="file" class="input-file" multiple>
        <label for="file" class="label label-file">
            <i class="joint-upload icon"></i>
            <span class="text text--fz-14 upload__text">
                <?php echo get_post_meta( get_the_ID(), 'joint_send_file_text', true ); ?>
            </span>
        </label>
    </div>
    <button type="submit" class="button form-button">
        <span class="button-text">
            <?php echo get_post_meta( get_the_ID(), 'joint_send_submit_text', true ); ?>
        </span>
    </button>
</form>

这是 JS 代码:

function formSend(e, form) {
    e.preventDefault()

    if (formValidate(form)) return

    let backFile = jointAjax.ajaxurl
    let curPage = ''

    let formData = new FormData(form)

    if (form.classList.contains('form-contacts')) {
       curPage = 'contacts'
    }
    else if (form.classList.contains('form-send')){
        curPage = 'send'
        let uploadFiles = []
        for (let single of form.file.files) {
            uploadFiles.push(single)
        }
        console.log(uploadFiles[0])
        formData.append('file', uploadFiles)
    }
    else {
        return
    }

    formData.append('action', curPage)

    fetch(backFile, {
       method: 'POST',
       body: formData,
    })
        .then(form.reset())
        .catch(error => {
            error.json().then(response => {
               alert(response.message)
            })
        })
}

这是 PHP 代码:

add_action('wp_ajax_send', 'joint_send_send_form');
add_action('wp_ajax_nopriv_send', 'joint_send_send_form');
function joint_send_send_form() {
    global $joint_settings;

    $data = json_encode($_POST);
    $data = json_decode($data, true);

    $attachment = array();
    if (isset($_FILES['file'])) {
        foreach($_FILES['file'] as $key => $file) {
            $attachment[] = $file['tmp_name'] . $file['name'];
        }
    }

    $mailBody = '';

    foreach ($data as $key => $value) {
        if ($key === 'action' || $key === 'file') continue;
        if (!empty($data[$key]))
            $mailBody .= '<p><strong>' . ucfirst($key) . ':</strong> ' . esc_html($value) . '</p>';
    }

    $headers = array(
        'From: Joint Admin <' . SMTP_FROM . '>',
        'content-type: text/html'
    );

    wp_mail(
        $joint_settings['send_mail_to'],
        $joint_settings['send_mail_theme'],
        $mailBody,
        $headers,
        WP_CONTENT_DIR . '\\' . $_FILES['file']['name']
    );

    // wp_send_json_success($_FILES['file']['tmp_name'] . '\\' . $_FILES['file']['name']);

}

我已经查看了各种论坛、文章和视频,但我似乎无法完成任务。

在 wp_mail 中,我们必须将完整路径传递给文件,但我们从哪里获得该路径? 而且无论我如何尝试处理多个文件,函数都只返回最后一个文件的名称作为回复。

SMTP 设置正确。电子邮件进来了,但没有文件。

请帮忙 - 我不知道该怎么办了。

【问题讨论】:

  • 在文件输入元素中使用 name="file[]" 而不是 name="file"。这将传递一组文件项而不是单个项。请注意,该结构对于多个文件并不直观。无法真正帮助 WordPress 部分,但我怀疑你想要 tmp_name 元素。
  • @TangentiallyPerpendicular ,非常感谢。您对输入名称的建议派上了用场,如果不是您,我可能会在另一天为这项任务苦苦挣扎)

标签: javascript php ajax wordpress send


【解决方案1】:

我想通了 - 我查看了 Contact form 7 插件中的实现并理解了其中的原理。

基本思路是先将上传的文件移动到网站内部目录,然后从那里发送到邮箱。

JS中我只改变了一件事(你可以发送文件请求而不需要处理):

else if (form.classList.contains('form-send')){
    formData.append('file', form.file.files)
    curPage = 'send'
}

我的处理函数如下所示:

add_action('wp_ajax_send', 'joint_send_send_form');
add_action('wp_ajax_nopriv_send', 'joint_send_send_form');
function joint_send_send_form() {
    global $joint_settings;

    $data = json_encode($_POST);
    $data = json_decode($data, true);

    $mailBody = '';

    foreach ($data as $key => $value) {
        if ($key === 'action' || $key === 'file') continue;
        if (!empty($data[$key]))
            $mailBody .= '<p><strong>' . ucfirst($key) . ':</strong> ' . esc_html($value) . '</p>';
    }

    $headers = array(
        'From: Joint Admin <' . SMTP_FROM . '>',
        'content-type: text/html'
    );

    $file = $_FILES['file'];
    // joint_array_flatten() - converts multi-dimensional array to a flat array
    $names = joint_array_flatten( $file['name'] );
    $tmp_names = joint_array_flatten( $file['tmp_name'] );

    $uploads = wp_get_upload_dir()['basedir'];
    $uploads_dir = path_join( $uploads, 'joint_uploads' );

    $uploaded_files = array();

    foreach ( $names as $key => $filename ) {
        $tmp_name = $tmp_names[$key];

        if ( empty( $tmp_name ) or ! is_uploaded_file( $tmp_name ) ) {
            continue;
        }

        // joint_antiscript_file_name() - converts a file name to one that is not executable as a script
        $filename = joint_antiscript_file_name( $filename );

        $filename = wp_unique_filename( $uploads_dir, $filename );
        $new_file = path_join( $uploads_dir, $filename );

        if ( false === @move_uploaded_file( $tmp_name, $new_file ) ) {
            wp_send_json_error( json_encode( array('message' => 'Upload error') ) );
            return;
        }

        // Make sure the uploaded file is only readable for the owner process
        chmod( $new_file, 0400 );

        $uploaded_files[] = $new_file;
    }

    wp_mail(
        $joint_settings['send_mail_to'],
        $joint_settings['send_mail_theme'],
        $mailBody,
        $headers,
        $uploaded_files
    );

    // Deletes sent files as they are on the email
    foreach ( $uploaded_files as $filepath ) {
        wp_delete_file( $filepath );
    }
}

我从 Contact form 7 中窃取了几个特征。反脚本确实有用,但是否需要joint_array_flatten - 我不知道,但我已经太累了,不想再想了。

最后我从目录中删除下载的文件,这样它就不会被阻塞。

此外,正如用户 @TangentiallyPerpendicular 正确指出的那样,您需要在 file-input 名称中添加 [] 才能发送多个文件:

<input id="file" type="file" name="file[]" class="input-file" multiple>

否则,就是这样。我希望有一天这会对其他人有所帮助,并且他们不必像我一样为类似的任务而苦恼)

【讨论】:

    猜你喜欢
    • 2019-10-08
    • 2013-04-01
    • 1970-01-01
    • 2013-08-20
    • 2012-07-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多