Stank0V01's avatar

Get the ftp upload percentages with Laravel FileSystem

Hello guys, so i have an app like wetransfer.com, so i'm trying to get the upload percentage from the ftp.

Here is my upload controller.

  public function upload(UploadRequest $request)
    {
        /*
         * If user have registration, make his own folder with name of his email address
         */
        $folder = !Auth::user() ? md5(Str::random(10) . $request->ip() . time()) : Auth::user()->email;

        // Get all of the files
        $files = $request->file('cloudesk_upload');

        // Generate Short url
        $shortUrl = env("SHORT_URL") . "/" . Str::random(5);

        /*
         * Generate a new short link
         */
        $link = new Link();
        $link->url = $shortUrl;
        $link->save();


        /*
         * Data insert
         */
        $data = [];

        foreach ($files as $file) {
            $filename = md5($file->hashName());
            $data[] = [
                "original_name" => $file->getClientOriginalName(),
                "unique_name" => $filename,
                "last_modified" => time(),
                "server_path" => env("UPLOAD_MAIN_DIR") . "$folder/$filename",
                "size" => $file->getSize(),
                "extension" => $file->getClientOriginalExtension(),
                "in_dir" => $folder,
                "link_id" => $link->id,
                "delete_at" => Carbon::now()->addWeek(1),
                "user_id" => Auth::user() ? Auth::user()->id : null
            ];

            Storage::disk('fu_ftp')->put("home/" . "$folder", $file);
        }

        File::insert($data);

        return response()->json([
            "success" => "file was uploaded successfully",
            "file" => $data,
            "url" => $link->url
        ], 200);
    }

And my front end side:

   const onDrop = useCallback(acceptedFiles => {
        setShowUpload(false);
        const uploading = acceptedFiles.map(file => {

            console.log(file);

            const formData = new FormData();
            formData.append("cloudesk_upload[]", file);
            const xhr = new XMLHttpRequest();
            xhr.upload.onprogress = event => {
                const percentage = parseInt((event.loaded / event.total) * 100);
                setUploadPercentages(percentage);
            };
            xhr.onreadystatechange = () => {
                if (xhr.readyState !== 4) return;
                if (xhr.status !== 200) {
                    console.log('error'); // Handle error here
                }
                console.log('success'); // Handle success here
            };

            setTimeout(() => {
                xhr.open('POST', `${window.API_URL}/upload`, true);
                xhr.send(formData);
            }, 3000)
        });
    }, [])

It's work but just show the percentage of how many form data is sended to the backend.

How to get how many of that file are uploaded to the ftp. Thank u in advice :)

0 likes
9 replies
Stank0V01's avatar

@bobbybouwmann Yes, this work but i can't track if the file is uploaded fully on the ftp or not. Some another advice?

bobbybouwmann's avatar

You can do a check if the files exist, right? Just doing an ajax call to the backend should fix that

Stank0V01's avatar

@bobbybouwmann Yes i know, but if the file is like 3 GB , the file is being created on the ftp but it`s not fully uploaded.

Stank0V01's avatar

What im trying to explain is that the file is uploaded and created on the ftp, but the file on the ftp is not fully uploaded, and it's get some time to be uploaded fully.

I want something like wetransfer.com go and check it. Thanks.

For now, i just research about chunk uploading.

kbush's avatar

This isn't doable within a single request like you want. The only reason you can get a progress bar in JS is because the browser is handling the transfer. After the transfer is done, you're doing a server-to-server transfer and the browser has no awareness of it. All the browser knows is it is waiting for the server to send back a response.

To get something like this to work, you're probably going to need your route that receives the file to drop a job on a queue. Your job does the background server-to-server transfer. It'd probably be a pain to get the progress out and easier to indicate if the process completed as expected or not. In either case, this job is going to have to update a record somewhere to record progress or completion/failure(alternatively you could send an email or something with the result).

If the original upload route returns a job id, you can have the JS check another route after the upload with that job id and get back whatever status information you chose to go with. Have it check every second or so until error or completion.

Stank0V01's avatar

Yes. You exactly describe my problem. Can you prefer something to learn and research about it, or some example code. Thanks

martinbean's avatar
Level 80

@stank0v01 You need to upload the file in parts. You shouldn’t be trying to upload a 3 GB file all in one go. Look into chunked/multi-part uploading.

Please or to participate in this conversation.