f3-factory / fatfree-core

Fat-Free Framework core library
GNU General Public License v3.0
207 stars 88 forks source link

Uploading unedited camera image fails with web->receive() #275

Closed jusrombawa closed 5 years ago

jusrombawa commented 5 years ago

When uploading (specifically) unedited images straight from camera, the upload fails. Cropped images are fine, and so are images from anywhere else. I haven't seen anyone encounter the same issue so I'm submitting it here.

var_dump of $files:

array(1) { ["uploads/img-20190421-123726.jpg"]=> bool(false) }

F3 version 3.6 Image came from camera of Android 8.0.0 device, but it also happens with other Android versions I've tried.

Rayne commented 5 years ago

Could it be possible that the images are exceeding the upload limit of your PHP configuration?

jusrombawa commented 5 years ago

Huh. It might be. I'll try enlarging the file upload limit. If it works, I'll close this issue immediately. Thanks for pointing it out.

jusrombawa commented 5 years ago

Still doesn't work, sorry. I already increased the limit to 10MB, the file is just around 3MB.

ikkez commented 5 years ago

From a backend point of view, the device itself shouldnt make a difference. How are you uploading images? Is it a website form on a mobile device you're referring to? You have the enctype="multipart/form-data" attribute on your <form>tag or equivalent header set for an ajax request?

jusrombawa commented 5 years ago

The site is available for both desktop and mobile. I've uploaded them using both, but the same thing happens. Yes, I do have those in the ajax request. And I know it doesn't make sense, idk why unedited photos specifically from Android devices won't upload.

ikkez commented 5 years ago

please log the sending/received header data or debug the request an take a look at the $_FILES global to find any difference. I doubt that there's anything framework related to this issue, so the problem is maybe the image file or mobile browser, or your web->receive() implementation, which you have not shared yet. Are you use you have raised the upload limit correctly for this test? maybe try even 20M just to be sure.. you need to fix this at post_max_size and at upload_max_filesize.

bcosca commented 5 years ago

Are you sure upload_max_filesize and post_max_size are set to the appropriate limits?

jusrombawa commented 5 years ago

Hi sorry I may not be able to make a log right now, as I still have a lot on my plate. I'll just show the limits and show one of the functions I use it on for now to clarify the situation. I hope it helps,

php.ini

post_max_size=20M
upload_max_filesize=10M

JQuery:

    $("#change-pic-submit").click(function(){

        var form = $("#change-pic-form")[0];
        var data = new FormData(form);

        $.ajax({
            type: "POST",
            enctype: "multipart/form-data",
            url: "/uploadPhoto",
            data: data,
            processData: false,
            contentType: false,
            cache: false,
            timeout: 600000,
            success: function(data){
                window.location.reload();
            },
            error: function(jqXHR, exception)
            {
                alert(jqXHR.responseText);
            }

        });
    });

PHP:

function uploadPhoto(){
        $this->f3->set('UPLOADS','uploads/'); // don't forget to set an Upload directory, and make it writable!
        $overwrite = true; // set to true, to overwrite an existing file; Default: false
        $slug = true; // rename file to filesystem-friendly version
        $web = \Web::instance();
        $files = $web->receive(function($file,$formFieldName){
                var_dump($file);
                /* looks like:
                  array(5) {
                      ["name"] =>     string(19) "csshat_quittung.png"
                      ["type"] =>     string(9) "image/png"
                      ["tmp_name"] => string(14) "/tmp/php2YS85Q"
                      ["error"] =>    int(0)
                      ["size"] =>     int(172245)
                    }
                */
                //check if image
                /*if($file["type"] != "image/png" || $file["type"] != "image/gif" || $file["type"] != "image/jpeg" || $file["type"] != "image/pjpeg")
                    return false;*/
                //check if < 8 MB
                if($file['size'] > (8 * 1024 * 1024))
                    return false;
                return true;
            },
            $overwrite,
            $slug
        );
        if($files[0] == true)
        {   
            //get filename, actually the key for first (and only) array element of $files
            $filename =  key($files); //old path: /uploads/filename.ext
            $username = $this->f3->get("SESSION.user");
            $newfile = "uploads/". $username ."/profile.".pathinfo($filename)["extension"]; //new path: /uploads/current username/profile.ext
            //create folder if not yet made
            if (!file_exists("uploads/". $username ."/")) {
                mkdir("uploads/". $username ."/", 0777, true);
            }
            rename($filename, $newfile);
            //change user profile path
            $um = new UserMapper($this->db);
            $rm = new ReviewerMapper($this->db);
            $um->load(array("username = ?", $username));
            $rm->load(array("user_fk = ?", $um->id));
            $rm->profile_img_path = $newfile;
            $rm->save();
            $this->f3->set("SESSION.profileImagePath", $newfile);
        }
        else
        {
            $info = "Upload failed.";
            $this->f3->set('SESSION.info', $info);
        }
    }

At around rename($filename, $newfile), it throws an error because it can't see the unedited file. That's why I set a condition for if($files[0] == true), it will proceed with file modification. Otherwise, notify that upload failed.

ikkez commented 5 years ago

Please reopen in the google board if problem persists. thanks