19

Im using Laravel framework with Intervention Image library to upload and process images on my page. Everything works fine until I try to update .jpg images taken from mobile devices or from cameras. These images have MIME type application/octet-stream instead of image/jpeg. When I try to upload image with this command:

Image::make($thumb)->resize($this->twidth, $this->theight)->save($this->destination."/".$filename);

I get error:

Unable to read image from file

One uncomfortable solution is open that images in MS Paint and resave them, which will change MIME type to 'image/jpeg' and make it possible to upload it. But I would like to evade this solution at all cost.

EDIT:

I was trying to fix it by this command:

$img = imagecreatefromstring($thumb);

but it returns error: imagecreatefromstring(): Empty string or invalid image

Is there a way how to handle this type of images?

Tomas Turan
  • 1,195
  • 3
  • 17
  • 27
  • [Did you search SO before asking](http://stackoverflow.com/questions/5942666/php-create-image-from-application-octet-stream)? – dbf Dec 18 '14 at 09:21
  • Yes i did, but didnt found this answer – Tomas Turan Dec 18 '14 at 09:28
  • by the way, it doesn't work for me – Tomas Turan Dec 18 '14 at 09:52
  • I am having the same issue with uploads from Android. I am getting **imagecreatefromstring(): gd warning: one parameter to a memory allocation multiplication is negative or zero, failing operation gracefully** when I try to use `imagecreatefromstring(//UPLOAD FILE CONTENTS//)` – Mladen Janjetovic Jan 12 '16 at 09:59
  • What is there in the $thumb, a simple string with $path or FileUpload object? – Ehs4n Jan 19 '16 at 05:13
  • Are you using the GD or Imagick driver for Intervention? – Govert Verschuur Dec 27 '19 at 13:35
  • Does this answer your question? [PHP create image from application/octet stream](https://stackoverflow.com/questions/5942666/php-create-image-from-application-octet-stream) – N69S Feb 20 '20 at 08:43

6 Answers6

1

Check upload_max_filesize in php.ini. It was reason in my case.

G.Baghashvili
  • 190
  • 1
  • 2
  • 11
1

Well, In such a case you can remove Laravel validation rule mimes, and instead, you can validate the image by its extension using PHP.

Your validation rule will look like this.

$request->validate([
    'image' => 'required',
]);

Validating image using file extension will look like this

if (! in_array($request->file('image')->clientExtension(), ['jpg', 'jpeg', 'png'])) {
   // not a valid image
}
Kamlesh Suthar
  • 182
  • 2
  • 8
0

You may give this a try and convert it to Laravel

//The file post to the server
$image = $_FILES['imgfile'];

//array for type if octet
$MimeType = array(
    'useNew' => false,
    'type' => '' 
);

if($image['type'] == "application/octet-stream"){
    $imageMimeSize = getimagesize($img['tmp_name']); // get temporary file REAL info
    $MimeType['type'] = $imageMimeSize['mime']; //set in our array the correct mime
    $MimeType['useNew'] = true; //set to true for next if
}

//now check if we will use the MimeType or the one sent by browser
//$mimeCheck is the things you want to check. In my case i just wanted PNG or JPG
if($MimeType['useNew'] == true){ //if true, use MimeType to check file/image file
    $mimeCheckType = ($MimeType['type'] != "image/png" && $MimeType['type'] != "image/jpeg" && $MimeType['type'] != "image/jpg") && $MimeType['type'] != "image/gif");
}else{ //if not using real mime, go with the one device sent to us or browser sent us
    $mimeCheckType = ($img['type'] != "image/png" && $img['type'] != "image/jpeg" && $img['type'] != "image/jpg");
}

//returns error if image not png/jpg/jpeg/gif
if($mimeCheck){
    //return some error
}

for more doc. on this visit this link: Source document

if you like to go extreme you can try to format this to Laravel

<?php
// Retrieve JPEG width and height without downloading/reading entire image.
function getjpegsize($img_loc) {
    $handle = fopen($img_loc, "rb") or die("Invalid file stream.");
    $new_block = NULL;
    if(!feof($handle)) {
        $new_block = fread($handle, 32);
        $i = 0;
        if($new_block[$i]=="\xFF" && $new_block[$i+1]=="\xD8" && $new_block[$i+2]=="\xFF" && $new_block[$i+3]=="\xE0") {
            $i += 4;
            if($new_block[$i+2]=="\x4A" && $new_block[$i+3]=="\x46" && $new_block[$i+4]=="\x49" && $new_block[$i+5]=="\x46" && $new_block[$i+6]=="\x00") {
                // Read block size and skip ahead to begin cycling through blocks in search of SOF marker
                $block_size = unpack("H*", $new_block[$i] . $new_block[$i+1]);
                $block_size = hexdec($block_size[1]);
                while(!feof($handle)) {
                    $i += $block_size;
                    $new_block .= fread($handle, $block_size);
                    if($new_block[$i]=="\xFF") {
                        // New block detected, check for SOF marker
                        $sof_marker = array("\xC0", "\xC1", "\xC2", "\xC3", "\xC5", "\xC6", "\xC7", "\xC8", "\xC9", "\xCA", "\xCB", "\xCD", "\xCE", "\xCF");
                        if(in_array($new_block[$i+1], $sof_marker)) {
                            // SOF marker detected. Width and height information is contained in bytes 4-7 after this byte.
                            $size_data = $new_block[$i+2] . $new_block[$i+3] . $new_block[$i+4] . $new_block[$i+5] . $new_block[$i+6] . $new_block[$i+7] . $new_block[$i+8];
                            $unpacked = unpack("H*", $size_data);
                            $unpacked = $unpacked[1];
                            $height = hexdec($unpacked[6] . $unpacked[7] . $unpacked[8] . $unpacked[9]);
                            $width = hexdec($unpacked[10] . $unpacked[11] . $unpacked[12] . $unpacked[13]);
                            return array($width, $height);
                        } else {
                            // Skip block marker and read block size
                            $i += 2;
                            $block_size = unpack("H*", $new_block[$i] . $new_block[$i+1]);
                            $block_size = hexdec($block_size[1]);
                        }
                    } else {
                        return FALSE;
                    }
                }
            }
        }
    }
    return FALSE;
}
?>

to convert image to JPEG try this:

<?php
// Access the $_FILES global variable for this specific file being uploaded
// and create local PHP variables from the $_FILES array of information
$fileName = $_FILES["uploaded_file"]["name"]; // The file name
$fileTmpLoc = $_FILES["uploaded_file"]["tmp_name"]; // File in the PHP tmp folder
$fileType = $_FILES["uploaded_file"]["type"]; // The type of file it is
$fileSize = $_FILES["uploaded_file"]["size"]; // File size in bytes
$fileErrorMsg = $_FILES["uploaded_file"]["error"]; // 0 for false... and 1 for true
$fileName = preg_replace('#[^a-z.0-9]#i', '', $fileName); // filter the $filename
$newExt = explode(".", $fileName); // Split file name into an array using the dot
$fileExt = end($newExt); // Now target the last array element to get the file extension

// START PHP Image Upload Error Handling --------------------------------
if (!$fileTmpLoc) { // if file not chosen
    echo "ERROR: Please browse for a file before clicking the upload button.";
    exit();
} else if($fileSize > 5242880) { // if file size is larger than 5 Megabytes
    echo "ERROR: Your file was larger than 5 Megabytes in size.";
    unlink($fileTmpLoc); // Remove the uploaded file from the PHP temp folder
    exit();
} else if ($fileErrorMsg == 1) { // if file upload error key is equal to 1
    echo "ERROR: An error occured while processing the file. Try again.";
    exit();
}
// END PHP Image Upload Error Handling ----------------------------------
// Place it into your "uploads" folder mow using the move_uploaded_file() function
$moveResult = move_uploaded_file($fileTmpLoc, "uploads/$fileName");
// Check to make sure the move result is true before continuing
if ($moveResult != true) {
    echo "ERROR: File not uploaded. Try again.";
    exit();
}
// ---------- Start Universal Image Resizing Function --------
$target_file = "uploads/$fileName";
$resized_file = "uploads/resized_$fileName";
$wmax = 500;
$hmax = 500;
ak_img_resize($target_file, $resized_file, $wmax, $hmax, $fileExt);
// ----------- End Universal Image Resizing Function ----------
// ---------- Start Convert to JPG Function --------
if (strtolower($fileExt) != "jpg") {
    $target_file = "uploads/resized_$fileName";
    $new_jpg = "uploads/resized_".$newExt[0].".jpg";
    ak_img_convert_to_jpg($target_file, $new_jpg, $fileExt);
}
// ----------- End Convert to JPG Function -----------

echo "The file named <strong>$fileName</strong> uploaded successfuly.<br /><br />";
echo "It is <strong>$fileSize</strong> bytes in size.<br /><br />";
echo "It is an <strong>$fileType</strong> type of file.<br /><br />";
echo "The file extension is <strong>$fileExt</strong><br /><br />";
echo "The Error Message output for this upload is: $fileErrorMsg";
?>

for clearer documentation of the above code

HTML

    <div id="profilephoto" class="profilephoto" data-coupling="#content2"><img src="<?php echo $avatar ?>"></div>
    <div id="content2" style="display: none;" class="uploadbutton" data-coupling="#content2">
        <form id="imguploadin" method="POST" action="image_upload_script.php">
            <label class="cabinet"> <i class="icon-upload-alt"></i> Choose Photo
                <input type="file" name="uploaded_file" class="file" onchange="handleFiles(this.files)"/>
            </label>
        </form>
    </div>

jQuery/JavaScript

function handleFiles(files) {
    for (var i = 0; i < files.length; i++) {
        var file = files[i];
        var imageType = /image.*/;

        if (!file.type.match(imageType)) {
            continue;
        }

        var img = document.createElement("img");
        img.classList.add("newphoto");
        img.file = file;
        profilephoto.appendChild(img);

        var reader = new FileReader();
        reader.onload = (function(aImg) { return function(e) { aImg.src = e.target.result; }; })(img);
        reader.readAsDataURL(file);
        var eventt = jQuery.Event("submit");

        $("#imguploadin").trigger(eventt);
    }
}

PHP (image_upload_script.php)

<?php
session_start();
// Access the $_FILES global variable for this specific file being uploaded
// and create local PHP variables from the $_FILES array of information
$username = $_SESSION["username"];
$fileName = $_FILES["uploaded_file"]["name"]; // The file name
$fileTmpLoc = $_FILES["uploaded_file"]["tmp_name"]; // File in the PHP tmp folder
$fileType = $_FILES["uploaded_file"]["type"]; // The type of file it is
$fileSize = $_FILES["uploaded_file"]["size"]; // File size in bytes
$fileErrorMsg = $_FILES["uploaded_file"]["error"]; // 0 for false... and 1 for true
$kaboom = explode(".", $fileName); // Split file name into an array using the dot
$fileExt = end($kaboom); // Now target the last array element to get the file extension
// START PHP Image Upload Error Handling --------------------------------------------------
if (!$fileTmpLoc) { // if file not chosen
    echo "ERROR: Please browse for a file before clicking the upload button.";
    exit();
} else if ($fileSize > 1242880) { // if file size is larger than 5 Megabytes
    echo "ERROR: Your file was larger than 5 Megabytes in size.";
    unlink($fileTmpLoc); // Remove the uploaded file from the PHP temp folder
    exit();
} else if (!preg_match("/.(gif|jpg|png)$/i", $fileName)) {
    // This condition is only if you wish to allow uploading of specific file types
    echo "ERROR: Your image was not .gif, .jpg, or .png.";
    unlink($fileTmpLoc); // Remove the uploaded file from the PHP temp folder
    exit();
} else if ($fileErrorMsg == 1) { // if file upload error key is equal to 1
    echo "ERROR: An error occured while processing the file. Try again.";
    exit();
}
// END PHP Image Upload Error Handling ----------------------------------------------------
// Place it into your "uploads" folder mow using the move_uploaded_file() function
$moveResult = move_uploaded_file($fileTmpLoc, "images/users/$username.$fileExt");
// Check to make sure the move result is true before continuing
if (!$moveResult) {
    echo "ERROR: File not uploaded. Try again.";
    unlink($fileTmpLoc); // Remove the uploaded file from the PHP temp folder
    exit();
}
// ---------- Include Adams Universal Image Resizing Function --------
include_once("ak_php_img_lib_1.0.php");
$target_file = "images/users/$username.$fileExt";
$resized_file = "images/users/resized_$username.$fileExt";
$wmax = 200;
$hmax = 150;
ak_img_resize($target_file, $resized_file, $wmax, $hmax, $fileExt);
$thumbnail = "images/users/thumb_$username.$fileExt";
$wthumb = 150;
$hthumb = 150;
ak_img_thumb($target_file, $thumbnail, $wthumb, $hthumb, $fileExt);
// ----------- Write Image File path to the server ---------------------------------
$sql_user = "myuser";
$sql_pass = "mypassword";
$sql_ip = "localhost";
$sql_DB = "mydb";
if ($moveResult != true)
    echo("couldnt write file path to database due to unsuccesfull upload");
    else {
    $mysqli = new mysqli($sql_ip, $sql_user, $sql_pass, $sql_DB);
    if ($stmt = $mysqli->prepare("UPDATE users SET avatar=? WHERE username=?")) {
        $user = $_SESSION['username'];
        $avatar = $resized_file;
        $stmt->bind_param('ss', $avatar, $user);
        $stmt->execute();
        $stmt->close();
        //header('location: profile.html');
        return true;
    }
    $mysqli->close();
    }

// ----------- End Adams Universal Image Resizing Function -----------
// Display things to the page so you can see what is happening for testing purposes
echo "The file named <strong>$username.$fileExt</strong> uploaded successfuly.<br /><br />";
echo "It is <strong>$fileSize</strong> bytes in size.<br /><br />";
echo "It is an <strong>$fileType</strong> type of file.<br /><br />";
echo "The file extension is <strong>$fileExt</strong><br /><br />";
echo "The Error Message output for this upload is: $fileErrorMsg";
?>

The Document edited can be found here source

Community
  • 1
  • 1
Michael
  • 588
  • 11
  • 19
  • I saw it here http://stackoverflow.com/a/11316048/1090395 But that is only the check if uploaded file is png, jpg or gif, right? I can get that much easier in Laravel with File::mimeType($file). We need here a way to change mime od application/octet-stream to image/jpeg once the file is uploaded from Android app – Mladen Janjetovic Jan 12 '16 at 11:48
  • but you question is not clear, you only state your problem. I will add/edit my answer now – Michael Jan 12 '16 at 12:21
  • This is not my question, I am only giving the award for right solution. His question was pretty clear to me – Mladen Janjetovic Jan 12 '16 at 12:36
  • after you upload the file from the sever then use the code above to convert it. – Michael Jan 12 '16 at 15:12
  • It is still not working. Did you take that from here https://www.developphp.com/video/PHP/Image-Resize-Function-Tutorial-jpg-gif-png-Change-Size If you did, you forgot the line where **ak_php_img_lib_1.0.php** is included. – Mladen Janjetovic Jan 13 '16 at 13:27
  • the ak_php_img_lib_1.0.php line does not matter, that is the reason why i put the function in the same file so that you will not have to use additional library and putting it in extra file, if you wish to use GD library i will post the link in my comment now – Michael Jan 13 '16 at 13:51
  • This where i formatted the code https://github.com/roicoroy/gallery/blob/master/ak_php_img_lib_1.0.php – Michael Jan 13 '16 at 13:58
  • Check the answer i just edited now or visit this link: http://stackoverflow.com/questions/15818668/error-when-uploading-file – Michael Jan 13 '16 at 14:16
  • But uploading image is not the problem. The problem is when we get the file on server side with mime **application/octet-stream**. We need to change it to **image/jpeg**, if it's possible at all. You just keep writhing the lots of code for image upload and saving it to data base or resize. And you are mentioning Laravel, and I can't see one Laravel specific thing in this code. – Mladen Janjetovic Jan 13 '16 at 20:14
  • you re not getting the logic, this what happen to above code: when you upload a image into a directory on a server it resized the image and convert it to JPEG, is the same logic that is happen when you re converting image from string – Michael Jan 13 '16 at 20:18
  • so am expecting you, you format it laravel language that what i mean – Michael Jan 13 '16 at 20:20
  • tell me where you re really getting stock with the code exactly. – Michael Jan 13 '16 at 20:23
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/100617/discussion-between-michael-and-mladen-janjetovic). – Michael Jan 13 '16 at 22:33
  • @MladenJanjetovic I could have not read the question 100% I have pooled my answer back. thanks letting me know that. – Maytham Fahmi Jan 17 '16 at 18:31
0

I would try to focus on how you are receiving your file. Try it this way at first:

$data = file_get_contents($_FILES['myphoto']['tmp_name']);
$image = imagecreatefromstring( $data );

it's a cite of answer on this topic.

Image::make(
    imagecreatefromstring(
        file_get_contents($_FILES['myphoto']['tmp_name'])
    )
);

// or maybe
$img = Image::make($_FILES['myphoto']['tmp_name']);

As of for Intervention image manual it should work.;

If it is not an answer, please show me what is code that assigns value to $thumb.

Community
  • 1
  • 1
yergo
  • 4,761
  • 2
  • 19
  • 41
0

First of all include Input namespace

use Illuminate\Support\Facades\Input;

then change the value of $thumb variable

$inputFileObj = Input::file('filename_here');
$thumb = $inputFileObj->getRealPath();

then use your code as it is.

Milan Katariya
  • 356
  • 1
  • 12
0

You can do this, If the mime type is octet-stream then encode it in the base64 and make image from the string or else make it normally.

$mime_type = $thumb->getMimeType();
$break = explode('/', $mime_type);
if($break[1] == "octet-stream"){
    $imagedata = file_get_contents($thumb);
    $base64 = base64_encode($imagedata);
    Image::make($base64)->resize($this->twidth, $this->theight)->save($this->destination."/".$filename);
}
else{
    Image::make($thumb)->resize($this->twidth, $this->theight)->save($this->destination."/".$filename);
}

I hope it'll be helpful

Khalid Khan
  • 3,017
  • 1
  • 11
  • 27