2

I would like to save an image into a varbinary(max) field in MSSQL.

The store method in my controller looks like this:

public function store(Request $request)
    {

        $vorname = $request->input('vorname');

        $nachname = $request->input('nachname');

        $file = $request->file('avatar');

        $extension = $file->clientExtension();

        $fullname = $nachname . "_" . $vorname . "." . $extension;

        $file->storeAs('avatars' , $fullname);

        $path = storage_path() . "\app\avatars\\". $fullname;

        $imageData = unpack("H*", file_get_contents($path));

        Mitarbeiter::create([

            'PersonalNr' => request('personalnr'),
            'Mitarbeiterschluessel' => request('mitarbeiterkey'),
            'Vorname' => $vorname,
            'Familienname' => $nachname,
            'Bild' => $imageData[1]

        ]);

        return view('welcome');

    }

I'm getting an error:

SQLSTATE[42000]: [Microsoft][ODBC Driver 11 for SQL Server][SQL Server]Die implizite Konvertierung vom nvarchar(max)-Datentyp in varbinary(max) ist nicht zulässig.

translated:

Implicit conversion from the nvarchar (max) data type to varbinary (max) is not allowed.

1
  • An off-topic question, why are you trying to store the image in the database? Laravel offers a great Storage API, why don't you use it? Any particular reason? Commented Apr 26, 2020 at 5:26

4 Answers 4

2

this code work for me

if($request->input('Image')){
    $datastring = file_get_contents($request->input('Image'));
    $data         = unpack("H*hex", $datastring);
    $data         = '0x'.$data['hex'];
    $photo = \App\TraineeImage::where('ID', 13)->first();
    $photo->update(['Image' =>  \DB::raw("CONVERT(VARBINARY(MAX), $data) ") ]);
}
Sign up to request clarification or add additional context in comments.

1 Comment

This worked for me after weeks of struggling to CAST the binary data
2

I recently came across similar requirement and did it like this. (Assuming $base64String is your string that contains image in base64 format)

$sql = "CAST(N'' AS xml).VALUE('xs:base64Binary(\"".$base64String."\")', 'VARBINARY(max)')";

UserProfilePicture::updateOrCreate(
    ['user_id' => $this->user_id],
    [
        'type' => $type,
        'size' => $size,
        'data' => DB::raw($sql),
    ],
);

2 Comments

after more than a week... this is the best solution
Thanks @BenjaminIni
1

I am faced with the same problem, but I figured out a way to make it work with Laravel's DB class.

Basically just like in any other language certain types cannot be implicitly converted, so are the types of MSSQL. Here is an image of all of the type conversion for MSSQL. enter image description here Notice that From nvarchar To varbinary you can only do Explicit conversion.

Since in PHP you don't have "binary" type and simply a string, we cannot store it directly into MSSQL. To solve this problem, we need to manually/explicitly cast our image into a binary/varbinary. Reading from conversions of binary/varbinary we need to call CAST or CONVERT on our image.

And since we want to do prepared statements, we can say CONVERT(VARBINARY(MAX), ?) and then bind it to the image value.

DB::statement(
    "INSERT INTO files (PersonalNr, Mitarbeiterschluessel, Vorname, Familienname, Bild) VALUES (?,?,?,?,CONVERT(VARBINARY(MAX), ?));", [
        request('personalnr'),
        request('mitarbeiterkey'),
        $vorname,
        $nachname,
        base64_encode(file_get_contents($path))
]);

Notice that I don't do any pack/unpack, but simply base64_encode'ed string, because as I understand you cannot pass binary from PHP to SQL that easily.

Comments

0

i know that this topics is very old but, this was my fix

$doc = file_get_contents($path);
$data = unpack("H*hex", $doc);
DB::connection("sqlsrv")->statement("INSERT INTO tb_docs (id, doc) VALUES (?,0x".$data['hex'].");",[$id]);

the field "doc" have as data type varbinary(max) without attribute FILESTREAM, in this field i stored files like JPG, PNG, PDF and work very well

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.