What would be the best way to achieve this?

HI, I am building an experiment form where there are 4 fields. It is a simple upload form, 3 upload fields, 1 input. It used to work great until i attempted to upload a large file in which it exeeded the web host upload limit (this can’t be changed). I read that a better way to upload large files is via chunking. I only need to chunk one input (main file) but i just cannot find anything anywhere to help. My endgame is you enter all the details, click submit which then the form does the chunking first, once done get name and then submit the rest of the data to the database for insertation. This is a cross between JS and PHP

Is this a poor way to do this? Should i use a library? What would be the best way to achieve it? All help much appreciated!

Content
Icon Img
Preview Img
Main File

My old code:

        if($_SERVER['REQUEST_METHOD'] == 'POST')
        {
            $this->csrf->CSRFTokenVerify();

            $files = [
                'icon_img' => $_FILES['icon_img']['name'],
                'iname' => generateRandomString(25),
                'preview_img' => $_FILES['preview_img']['name'],
                'pname' => generateRandomString(25),
                'item_file' => $_FILES['item_file']['name'],
                'fname' => generateRandomString(35),
            ];
            $formData = [
				'content' => trim($_POST['content']),
                'icon_img' => (empty($files['icon_img']) === TRUE ? '' : $files['iname'].'.'.pathinfo($files['icon_img'], PATHINFO_EXTENSION)),
                'preview_img' => (empty($files['preview_img']) === TRUE ? '' : $files['pname'].'.'.pathinfo($files['preview_img'], PATHINFO_EXTENSION)),
                'item_file' => (empty($files['item_file']) === TRUE ? '' : $files['fname'].'.'.pathinfo($files['item_file'], PATHINFO_EXTENSION)),
                'user_pin' => $_SESSION['upin'],
				'content_err' => '',
                'icon_img_err' => '',
                'preview_img_err' => '',
                'item_file_err' => '',
            ];		
            $data = [
                'getSettings' => $getSettings,
                'getNav' => $getNav,
                'getConstantUser' => $getConstantUser,
                'formData' => $formData,
                'title' => 'Upload an Item',
                'description' => '',
            ];

			if(empty($data['formData']['content'])) {
				$data['formData']['content_err'] = 'Content box is required!';
			}
            
			if(empty($_FILES['icon_img']['name']) === TRUE){
				$data['formData']['icon_img_err'] = 'A thumbnail image is required!';
			}
			if(empty($_FILES['preview_img']['name']) === TRUE){
				$data['formData']['preview_img_err'] = 'A preview image is required!';
			}
			if(empty($_FILES['item_file']['name']) === TRUE){
				$data['formData']['item_file_err'] = 'A main file is required!';
			}
            
            if(empty($data['formData']['name_err']) && empty($data['formData']['content_err']) && empty($data['formData']['icon_img_err']) && empty($data['formData']['preview_img_err']) && empty($data['formData']['item_file_err'])) {
                
                    $upload_errors = [];
                    $uploaded_files = [];
    
                    foreach(array("icon_img", "preview_img", "item_file") as $file_id) {
                        if(isset($_FILES[$file_id]) && isset($data['formData'][$file_id]) && $data['formData'][$file_id]) {
                            $upload = new Uploader($_FILES[$file_id]);
    
                            switch ($file_id) {
                                case "icon_img":
                                    $upload_id = "Thumbnail Image";
                                    $allowed_extensions = array('png', 'jpg', 'jpeg', 'gif');
                                    $allowed_types = array('image/jpeg','image/png','image/gif');
                                    $max_size = 2;
                                    $max_dimensions = array('200', '200');
                                    $upload_dir = "thumbnail";
                                    $file_name = $files['iname'];
                                    break;
                                case "preview_img":
                                    $upload_id = "Preview Image";
                                    $allowed_extensions = array('png', 'jpg', 'jpeg', 'gif');
                                    $allowed_types = array('image/jpeg','image/png','image/gif');
                                    $max_size = 3;
                                    $max_dimensions = array('1600', '800');
                                    $upload_dir = "preview";
                                    $file_name = $files['pname'];
                                    break;
                                default:
                                   // this here needs reforming to support chunking but i do not know where to start
                                    $upload_id = "File";
                                    $allowed_extensions = array('zip', 'rar');
                                    $allowed_types = array('application/zip', 'application/octet-stream', 'application/x-zip-compressed', 'multipart/x-zip', 'application/x-rar-compressed');
                                    $max_size = 96;
                                    $max_dimensions = false;
                                    $upload_dir = "files/" . SECURE_FOLDER;
                                    $file_name = $files['fname'];
                            }
    
                            if ($allowed_extensions)
                                $upload->allowed_extensions($allowed_extensions);
    
                            if ($allowed_types)
                                $upload->allowed_types($allowed_types);
    
                            if ($max_size)
                                $upload->max_size($max_size);
    
                            if ($max_dimensions)
                                $upload->max_image_dimensions($max_dimensions); // in pixels
    
                            if ($upload_dir)
                                $upload->path("uploads/test/items/" . $upload_dir);
    
                            $upload->name($file_name);
                            if ($upload->upload()) {
                                $uploaded_files[] = $upload->get_path($upload->get_error());
                            } else {
                                $upload_errors[] = $upload_id . " Upload: " . $upload->get_error();
                            }
                        }
                    }
    
                    if (count($upload_errors) > 0) {
                        foreach ($upload_errors as $error) {
                            echo $error . "<br>";
                        }
                        foreach ($uploaded_files as $file) {
                            @unlink($file);
                        }
                    } else {
                        if($this->m->addItem($formData)) {
                            flash('message', 'Your item has been submitted and is pending review!', 'alert alert-success mb-0');
                            redirect('test/dashboard');
                        } else{
                            die(LANG['something-went-wrong']);
                        }
                    }
            } else {
                $this->view('test/item/upload', $data);
            }
        } else {
            $formData = [
				'content' => '',
                'icon_img' => '',
                'preview_img' => '',
                'item_file' => '',
                'name_err' => '',
				'content_err' => '',
                'icon_img_err' => '',
                'preview_img_err' => '',
                'item_file_err' => '',
            ];
            $data = [
                'getSettings' => $getSettings,
                'getNav' => $getNav,
                'getConstantUser' => $getConstantUser,
                'formData' => $formData,
				'title' => 'Upload an item',
				'description' => ''
            ];
            $this->view('test/item/upload', $data);
            
        }

When you start changing the way you code to suit the host, it’s time to get a new host.

As to your post you may want to check out TUS

@benanamen how exactly would that work in my case. Would i use this one? https://github.com/ankitpokhrel/tus-php or this one https://github.com/tus/tus-js-client

Thanks

Depends on what your doing. Read the implementation descriptions here.

You say upload but perhaps you do not realize that has many possible meanings. Do you intend to do all of it in PHP? I think you need to do some of it in JavaScript.

Apparently you can use the JavaScript FileReader API to read BLOBs. So you can read a portion of the file and perhaps create temporary local files to be uploaded and then they can be combined by PHP in the server.

Another possibility might be the BitTorrent format. See christeredvartsen/php-bittorrent: PHP classes for encoding/decoding data to/from the BitTorrent format for a possible use of that. I am not sure of the details of how it can be used but BitTorrent is very popular for transferring large files.

Thanks. I will look into that. The one thing I am having loads of trouble with is doing form data alongside the file upload.

I can only find solutions with just the file. I need to be able to handle a form which includes input fields as well. So name, description and then file input etc. but when uploading it does the chunking.

Would it be too much to ask for a code sample? My endgame is literally a form that supports chunked uploads but can also can handle standard text fields. Thanks again

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.