ahoi's avatar
Level 5

Upload a file using api-routes

Hello everybody,

I am trying to upload an image using my api-routes and UIKit 3 Upload form.

This is my Vue-markup:

        <form class="uk-form" method="post" enctype="multipart/form-data">
            <div>
                <div class="uk-card uk-card-default uk-card-body uk-padding-remove">
                    <div class="js-upload uk-placeholder uk-text-center uk-width-expand uk-height-1-1">
                        <div uk-form-custom class="uk-position-center">
                            <input type="file" multiple>
                            <span class="uk-link uk-icon-link" uk-icon="icon: cloud-upload;  ratio: 3.5"
                                  v-show="!uploading"></span>
                            <span uk-spinner="ratio: 3.5" v-show="uploading"></span>
                        </div>
                    </div>
                </div>
            </div>
        </form>
<script>
export default {

    data () {
        return {
            images: [],
            uploading: false
        }
    },
    mounted () {

        axios
        .get ('/api/image/get')
        .then (response => (this.images = response.data));

        let tokenElement = document.head.querySelector ('meta[name="csrf-token"]');
        let token;

        if (tokenElement) {
            token = tokenElement.content;
        } else {
            console.error ('CSRF token not found: https://laravel.com/docs/csrf#csrf-x-csrf-token');
        }

        let vueInstance = this;

        UIkit.upload ('.js-upload', {

            url: '/api/image/upload',
            multiple: false,

            beforeSend: function (environment) {
                environment.data.append ('_token', token);
            },

            loadStart: function (e) {
                vueInstance.uploading = true;
            },

            completeAll: function (e) {
                setTimeout (function () {
                    vueInstance.uploading = false;
                }, 1000);

                 axios
                 .get ('/api/image/get')
                 .then (response => (vueInstance.images = response.data));
            }

        });

    }
}
</script>

And this is my api.php in /routes:

Route::middleware('auth:api')->get('/image/get', 'ImageApiController@getImage')
    ->name('image.get');

Route::post('/image/upload', 'ImageApiController@uploadImage')
    ->name('image.upload');

And this is my Controller:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;


class ImageApiController extends Controller
{
    
    
    /**
     * Edit the user images.
     *
     * @param \Illuminate\Http\Request $request
     *
     * @return \Illuminate\Http\JsonResponse
     */
    public function getImage(Request $request)
    {
        //Just testing
    }
    
    /**
     * Update the user image.
     *
     * @param  \Illuminate\Http\Request $request
     *
     * @return \Illuminate\Http\Resources\Json\
     *
     */
    public function uploadImage(Request $request)
    {
        //Just testing
        return $request;
    }
}

But unfortunately, the request does not contain any files? This is the upload response:

{
    "_token": "HtCltpExKsP1t...jh1P7oKmelSWp",
    "files": [
        {}
    ]
}

As always: Any help is highly appreciated!

0 likes
2 replies
ahoi's avatar
Level 5

Hello everybody,

I was working on this but I did not find a solution yet. Unfortunately there are not a lot UIKit upload examples out there...

I guess one of the problems is the passport: As I am calling an api route with auth:api middleware, I have to pass the tokens as long as I am using third-party-js (non-axios). But I have no idea how to do this here:

            url: '/api/image/upload',

But even if I remove the auth:api for testing purposes (as I did in my initial question), I do not get the file :-/ ?

Additionally I am posting the request header:

Anfrage
POST /api/image/upload HTTP/1.1
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryXUDay2vdApWbqt7r
Origin: http://127.0.0.1:8000
Host: 127.0.0.1:8000
Accept: */*
Connection: keep-alive
Accept-Language: de-de
Accept-Encoding: gzip, deflate
Cookie: XSRF-TOKEN=eyJpdiI6IlI2Sk5rUElvWkRBZVFSSkppcXd6cWc9PSIsInZhbHVlIjoidldsTFhPb0hhRktlRXRxNVdmaUtEUWx6YXZqN2FJd3k4NUtQaVNCekx4eW9xM3A2ZmRRU3hWV3c5TzdXTUEwQiIsIm1hYyI6ImI4Njg4NjcyMWQ4YzUzYjQ2ZGEwMzFmOWQ5ZGQxNGFhYTFiZWFkOGZmY2ExNWVmMmFmY2E5YjMwZTRkZDNmZGMifQ%3D%3D; laravel_token=eyJpdiI6IjVHQzQ4SXZCSjFjY1lZMFlSbFgwY0E9PSIsInZhbHVlIjoicUtQNmdWUmd4QlB4UklmXC9CZFExOU9MY1FjZXhlOGhlOEwzMHBBaVRXU1oxRXY3NFR1WUVuVmV3MjRaWEd3UjRKMzZnb01ybTB0cFNrWmJNOERWNlJpK1RPaE83OUJJcE4rT3NlXC9LSXpRRkRuR09SbjhUZSttWlhkQ0RhT045TXZPdkhEUVoxU1pLY3lzQmdKcnJzbUxmWUZFUmRpaEFvN2ppc05EUFlyYzIzQWJ5OGhKOEQyZUt5VGdcL1lmeERQUW5nbG5LUGxFajd0U25kcFlGeDNvdmJ5UjdMajZycmRxaEk5VXlRd3lQOGRqTG5pK3JJZm9iRVRwMUVXQlBPKyIsIm1hYyI6IjRkMDMxOTAzYTBlOTg3ZWViMDcwNDE1ZmU3NGQ5NmExODI2OWE1NjY3OGMxMzliMDFmN2M1ZTBhNjQxYTZlMjYifQ%3D%3D; webmasterplace_session=eyJpdiI6Ind6UncremtHK0MxVkZtR2p5M084bXc9PSIsInZhbHVlIjoiSTlPMmk4Y2ZyTkJNRnBmRGRUNzMzdVlBajZCOUNlWGpzd2hITGxiV1JcL1N6eWlUWTM3cmhrTHNMekJqQUVCS1kiLCJtYWMiOiI0ZmQzMzVhODI0YWVhMzM0NmYxODBiODE1OGE0OTcxMmQ3NTcxNmQ2ZmMyYTdjZDg1NDEwYzExOTAxNGU2OTFiIn0%3D; remember_web_59ba36addc2b2f9401580f014c7f58ea4e30989d=eyJpdiI6IjBDcnlZUFZ4NnRWclQyc0NuSENoMkE9PSIsInZhbHVlIjoiUFowN0wyRkc4M3JMQkxzVFdsWGZLS3JXTUNNMEFjbjY3TE5QWEM3aHVZRlNkcm90Q2dcL1MwaDVmQ05JcXdpZlk3U1VcL0xXeHlLWDBKNG9LSWpZajhzUlBTaE1IYjlHMVJUXC9NQitBOUJxa0E1VDhcL2g0amM2UkU4Z2ZhZW5SMFF6ZlcrVkpiTHRNUUtsaEhWRUNXeGk4XC9hS0hpSEc3QkErcmkyS1BNK2ZpWXc9IiwibWFjIjoiNWE3MjBiZDUxOTE1YWFjOThhZTFkNThlNjMyOGE1OTRkZGMyZTQ1N2YyZTE2ZTkxN2YwZTc5NDAzNDFjZmYyOCJ9; pagekit_auth=yQP9yFQ.ZB3wkYy9hqHROL8LzlzfAR0CWG7SV5L9VG5o1OHzZ.WLM220irt8UqeY; cookieconsent_status=dismiss; __utma=96992031.1766838628.1508232523.1508504389.1508504389.1; ga-disable-UA-5378787-5=true; _ga=GA1.1.1766838628.1508232523
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/11.1.2 Safari/605.1.15
Referer: http://127.0.0.1:8000/image/edit
Content-Length: 19902
X-Requested-With: XMLHttpRequest
ahoi's avatar
ahoi
OP
Best Answer
Level 5

I got something new:

I had to add

                environment.headers['X-Requested-With'] = 'XMLHttpRequest';
                environment.headers['X-CSRF-TOKEN'] = token;

And I am able to fetch files via $_FILES, but not via $request->allFiles(). So how can I get allFiles() working?

Please or to participate in this conversation.