如何在 Laravel 中正确使用音频文件类型验证?

问题描述 投票:0回答:1

我对 Laravel 还很陌生,正在尝试学习这个框架。我目前正在制作一个简单的帖子/排行榜页面,用户应该能够向其中上传音频文件。除了音频上传之外,一切正常。我不确定错误出在哪里。我还使用 vite 为我的组件使用 React 代码。

用于验证:我尝试使用 mime,例如音频/mpeg、mp3、mpeg、aac、wav。当我上传 mp3 时,它们都不起作用。它也不保存文件。最终我只是尝试使音频可为空,并且不添加进一步的验证。此时,它确实将我重定向到帖子页面,我可以在其中查看数据。但音频没有保存在任何地方。它基本上已经丢失了。

我将在下面添加所有必需的文件。我哪里做错了?

create_inzending_table.php:

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('inzendings', function (Blueprint $table) {
            $table->id();
            $table->string('title');
            $table->string('category');
            $table->timestamp('posted_at')->nullable();
            $table->string('upvotes')->nullable();
            $table->string('description');
            $table->string('posted_by');
            $table->string('audio');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('inzendingen');
    }
};

请求/StoreInzending.php:

<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class StoreInzending extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array<string, mixed>
     */
    public function rules()
    {
        return [
            'audio' =>'nullable',
            'title' => ['required', 'string', 'max:255'],
            'description' => ['required', 'string', 'max:255'],
            'posted_by' => ['required', 'string', 'max:255'],
            'posted_at' => ['nullable', 'date'],
            'category' => ['required', 'string', 'max:255'],
            'upvotes' => ['integer'],

        ];
    }
}

模型/Inzending.php:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Inzending extends Model
{
    protected $fillable = [
        'audio',
        'title',
        'description',
        'imageUrl',
        'posted_at',
        'posted_by',
        'category',
        'upvotes'
    ];
    
    use HasFactory;
}

路线/web.php:

Route::get('inzending', [InzendingController::class,'index'])->name('inzending.index');
Route::get('inzending/create', [InzendingController::class,'create'])->name('inzending.create');
Route::post('inzending', [InzendingController::class,'store'])->name('inzending.store');

CreateInzendingForm.jsx:

import React, { useState } from 'react';
import { Link, useForm, usePage } from '@inertiajs/react';
import InputError from '@/Components/InputError';
import InputLabel from '@/Components/InputLabel';
import PrimaryButton from '@/Components/PrimaryButton';
import TextInput from '@/Components/TextInput';
import SelectInput from '@/Components/SelectInput';
import FileInput from './FileInput';

export default function CreateInzendingForm({ mustVerifyEmail, status, className }) {
    const user = usePage().props.auth.user;
    const inzending = usePage()

    const { data, setData, patch, post, errors, processing, recentlySuccessful } = useForm({
        name: user.name,
        email: user.email,
        education: user.education,  
        cohort: user.cohort,
        title: inzending.title,
        description: inzending.description,
        posted_at: inzending.posted_at,
        category: inzending.category,
        posted_by: user.name,
        audio: inzending.audio,
    });

    const submit = (e) => {
        e.preventDefault();

        console.log(data);
        post(route('inzending.store'));
    }


    return (
        <section>
            <header>
                <h2 className="text-lg font-medium text-gray-900 dark:text-gray-100">Create Inzending</h2>
            </header>

            <form onSubmit={submit} encType='multipart/form-data' className="mt-6 space-y-6">
                <div>
                    <InputLabel htmlFor="title" value="Title" />

                    <TextInput
                        id="title"
                        className="mt-1 block w-full"
                        onChange={(e) => setData('title', e.target.value)}
                        required
                        isFocused
                        autoComplete="title"
                    />
                    <InputError className="mt-2" message={errors.title} />
                </div>
                <div>
                    <InputLabel htmlFor="description" value="Description" />

                    <TextInput
                        id="description"
                        className="mt-1 block w-full"
                        onChange={(e) => setData('description', e.target.value)}
                        required
                        isFocused
                        autoComplete="description"
                    />
                    <InputError className="mt-2" message={errors.description} />
                </div>
                <div>
                    <InputLabel htmlFor="category" value="Category" />

                    <SelectInput
                        id="category"
                        className="mt-1 block w-full"
                        onChange={(e) => setData('category', e.target.value)}
                        required
                        isFocused
                        autoComplete="category"
                    />
                    <InputError className="mt-2" message={errors.category} />
                </div>
                <div>
                    <InputLabel htmlFor="posted_by" value="Posted By" />

                    <TextInput
                        id="posted_by"
                        className="mt-1 block w-full"
                        value={data.name}
                        onChange={(e) => setData('posted_by', e.target.value)}
                        required
                        isFocused
                        autoComplete="posted_by"
                    />
                    <InputError className="mt-2" message={errors.posted_by} />
                </div>
                    <div>
                    <InputLabel htmlFor="audio" value="Audio" />

                    <FileInput
                        id="audio"
                        name="audio"
                        className="mt-1 block w-full"
                        onChange={(e) => setData('audio', e.target.value)}
                        required
                        isFocused
                        autoComplete="audio"
                    />
                    <InputError className="mt-2" message={errors.audio} />

                <div className="flex items-center gap-4">
                    <PrimaryButton disabled={processing}>Save</PrimaryButton>
                </div>
                </div>
            </form>
        </section>
    );
}

文件输入.jsx:

import { forwardRef, useEffect, useRef } from 'react';

export default forwardRef(function FileInput({ type = 'file', name, className = '', isFocused = false, ...props }, ref) {
    const input = ref ? ref : useRef();

    useEffect(() => {
        if (isFocused) {
            input.current.focus();
        }
    }, []);

    return (
        <div className="flex flex-col items-start">
            <input
                {...props}
                name={name}
                type={type}
                className={
                    'border-gray-300 dark:border-gray-700 dark:bg-gray-900 dark:text-gray-300 focus:border-indigo-500 dark:focus:border-indigo-600 focus:ring-indigo-500 dark:focus:ring-indigo-600 rounded-md shadow-sm ' +
                    className
                }
                ref={input}
            />
        </div>
    );
});

配置/文件系统.php:

'links' => [
        public_path('storage') => storage_path('app/public'),
        public_path('images') => storage_path('app/public/images'),
        public_path('videos') => storage_path('app/public/videos'),
        public_path('audio') => storage_path('app/public/audio'),
    ],

非常感谢任何帮助!

laravel validation upload vite
1个回答
0
投票

问题已解决!

事实证明这是一个简单的修复,就像我正在读取文件输入的 e.target.value 一样,该值记录了 C:akepath ile.mp3。不是实际的文件。

要解决此问题,请改为阅读 e.target.files[0]。

© www.soinside.com 2019 - 2024. All rights reserved.