Search code examples
laravelfile-uploadcontrollerstorelaravel-7

Laravel How to handle file upload: Can't save image filename


So I want to upload a picture but it only store its description correctly. The file is stored as "noimage.jpg" which means the filename isn't read. I'm using modal btw. My database is named galleries and the migration contains these:

  • $table->id();
  • $table->timestamps();
  • $table->string('upload');
  • $table->longtext('description')->nullable();

CONTROLLER:

public function store(Request $request)
    {
        $galleries=new Gallery;
        // Handle File Upload
        if($request->hasFile('upload')){
            // Get filename with the extension
            $filenameWithExt = $request->file('upload')->getClientOriginalName();
            // Get just filename
            $filename = pathinfo($filenameWithExt, PATHINFO_FILENAME);
            // Get just ext
            $extension = $request->file('upload')->getClientOriginalExtension();
            // Filename to store
            $fileNameToStore= $filename.$extension;
            // Upload Image
            $path = $request->upload('upload')->storeAs('public/upload', $fileNameToStore);
        
        // make thumbnails
            $thumbStore = 'thumb.'.$filename.'_'.time().'.'.$extension;
            $thumb = Image::make($request->file('upload')->getRealPath());
            $thumb->save('storage/upload/'.$thumbStore);        
        } else {
            $fileNameToStore = 'noimage.jpg';
        }

        $galleries->description = $request->input('description');
        $galleries->upload = $fileNameToStore;
        $galleries->save();
        
    }

FORM:

<form id="uploadForm">
                <div class="modal-body">
                    <input type="hidden" name="id" id="id">                       
                    
                    <!-- Upload image input-->
                    <div class="input-group mb-3 px-2 py-2 rounded-pill bg-secondary shadow-sm">
                        <input  type="file" name="upload" id="upload" onchange="readURL(this);" class="form-control border-0">
                        
                        <label id="upload-label" for="upload" class="font-weight-light text-muted">Choose file</label>

                        <div class="input-group-append">
                            <label for="upload" class="btn btn-light m-0 rounded-pill px-4"> <i class="fa fa-cloud-upload mr-2 text-muted"></i><small class="text-uppercase font-weight-bold text-muted">Choose file</small></label>
                        </div>
                    </div>

                    <!-- Uploaded image area-->
                    <p class="font-italic text-white text-center">The image uploaded will be rendered inside the box below.</p>
                    <div class="image-area mt-4 bg-white"><img id="imageResult" src="#" alt="" class="img-fluid rounded shadow-sm mx-auto d-block"></div>
                    <label>Caption</label>
                    <input type="textarea" class="form-control text-white" name="description" id="description">

                </div>
</form>

AJAX

<script>
$(document).ready(function(){   
    $.ajaxSetup({
        headers: {
            'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
        }
    });
//ADD PICTURE
    $('#btnUpload').click(function(){
        $('#uploadModal').modal('show');
    });

    $('#btnSave').click(function(){
        $.ajax({
            data: $('#uploadForm').serialize(),
            url: "{{ route('home.store') }}",
            type: "POST",
            dataType: 'json', 

            success: function(data){
                $('#uploadModal').modal('hide');
            },

            error: function(data){
                console.log('Error:', data);
            }
        });
    });
//Image reader to show pic when selected
    function readURL(input) {
        if (input.files && input.files[0]) {
            var reader = new FileReader();

            reader.onload = function (e) {
                $('#imageResult')
                    .attr('src', e.target.result);
            };
            reader.readAsDataURL(input.files[0]);
        }
    }

    $(function () {
        $('#upload').on('change', function () {
            readURL(input);
        });
    });

    var input = document.getElementById( 'upload' );
    var infoArea = document.getElementById( 'upload-label' );

    input.addEventListener( 'change', showFileName );
    function showFileName( event ) {
    var input = event.srcElement;
    var fileName = input.files[0].name;
    infoArea.textContent = 'File name: ' + fileName;
    }
});
</script>

Solution

  • Assuming you're using ajax to upload the file, you'll need to use a FormData object instead of .serialize()

        $.ajax({
            data: new FormData($('#uploadForm').get(0)),  // use formdata object
            url: "{{ route('home.store') }}",
            type: "POST",
            dataType: 'json', 
            contentType: false,  // required for
            processData: false,  // jquery ajax file upload
            success: function(data){
                $('#uploadModal').modal('hide');
            },
    
            error: function(data){
                console.log('Error:', data);
            }
        });