2
votes

For development im working on windows on my laravel project. Im trying to get file uploads working locally.

My upload code:

public function addPicture(Request $request, $id)
{
    $bathroom = Bathroom::withTrashed()->findOrFail($id);
    $validatedData = Validator::make($request->all(), [
        'afbeelding' => 'required|image|dimensions:min_width=400,min_height=400',
    ]);
    if($validatedData->fails())
    {
        return Response()->json([
            "success" => false,
            "errors" => $validatedData->errors()
        ]);
    }
    if ($file = $request->file('afbeelding')) {
        $img = Image::make($file);
        $img->resize(3000, 3000, function ($constraint) {
            $constraint->aspectRatio();
            $constraint->upsize();
        });
        $img->stream();
        $uid = Str::uuid();
        $fileName = Str::slug($bathroom->name . $uid).'.jpg';

        $this->createImage($img, 3000, "high", $bathroom->id, $fileName);
        $this->createImage($img, 1000, "med", $bathroom->id, $fileName);
        $this->createImage($img, 700, "thumb", $bathroom->id, $fileName);
        $this->createImage($img, 400, "small", $bathroom->id, $fileName);

        $picture = new Picture();
        $picture->url = '-';
        $picture->priority = '99';
        $picture->alt = Str::limit($bathroom->description,100);
        $picture->margin = 0;
        $picture->path = $fileName;
        $picture->bathroom_id = $id;
        $picture->save();

        return Response()->json([
            "success" => true,
            "image" => asset('/storage/img/bathroom/'.$id.'/small/'.$fileName),
            "id" => $picture->id
        ]);
    }
    return Response()->json([
        "success" => false,
        "image" => ''
    ]);
}

public function createImage($img, $size, $quality, $bathroomId, $fileName){
    $img->resize($size, $size, function ($constraint) {
        $constraint->aspectRatio();
        $constraint->upsize();
    });
    Storage::put(  $this->getUploadPath($bathroomId, $fileName, $quality), $img->stream('jpg',100));

}

public function  getUploadPath($bathroom_id, $filename, $quality = 'high'){
    $returnPath = asset('/storage/img/bathroom/'.$bathroom_id.'/'.$quality.'/'.$filename);
    echo $returnPath;

}

I did run: php artisan storage:link

And the following path is available D:\Documents\repos\projectname\storage\app. When I upload a file I get:

"message": "fopen(D:\Documents\repos\projectname\storage\app\): failed to open stream: No such file or directory", "exception": "ErrorException", "file": "D:\Documents\repos\projectname\vendor\league\flysystem\src\Adapter\Local.php", "line": 157,

And later on in the log:

 "file": "D:\\Documents\\repos\\projectname\\app\\Http\\Controllers\\Admin\\BathroomController.php",
        "line": 141, . 

which points to the following line.

Storage::put(  $this->getUploadPath($bathroomId, $fileName, $quality), $img->stream('jpg',100));

of the createImage function. How can I make it work on windows so that I can test my website locally?

4
What return $img->stream('jpg',100)?MrEduar
Does anything happen if you remove the trailing / from the path?Qumber

4 Answers

0
votes

I usually save images to public folder directly here is a working code from one of my projects

 $category = new Categories;
//get icon path and moving it
$iconName = time().'.'.request()->icon->getClientOriginalExtension();
 // the icon in the line above indicates to the name of the icon's field in 
 //front-end
$icon_path = '/public/category/icon/'.$iconName;
//actually moving the icon to its destination
request()->icon->move(public_path('/category/icon/'), $iconName);  
$category->icon = $icon_path;
//save the image path to db 
$category->save();
return redirect('/category/index')->with('success' , 'Category Stored Successfully');

with some modifications to fit your code it should work correctly

0
votes

I have faced the similar issue and have solved it in the following manner

In order to upload the file to any path follow these steps.

Create a new disk in config/filesystem.php and point it to any path you like e.g to D:/test or whatever

'disks' => [

    // ...

     'archive' => [
            'driver' => 'local',
            'root' => 'D:/test',
         ],

    // ...

Remember archive is the disk name you can tweak it to whatever. After that do config:cache

then to upload file to the specifed directory do something like

  $request->file("image_file_identifier")->storeAs('SubFolderName', 'fileName', 'Disk');

e.g

  $request->file("image_file")->storeAs('images', 'aa.jpg', 'archive');

Now to get the file use following code

      $path = 'D:\test\images\aa.jpg';



    if (!\File::exists($path)) {
        abort(404);
    }

    $file = \File::get($path);
    $type = \File::mimeType($path);

    $response = \Response::make($file, 200);
    $response->header("Content-Type", $type);

    return $response;


0
votes

I hope you are using Image Intervention here. If not, you can run the command:

      composer require intervention/image

This will install intervention on your project. Now use the following code to upload images locally.

You can call the function to save images this way:

if ($request->hasFile('image')) {
   $image = $request->file('image');
   //Define upload path
   $destinationPath = public_path('/storage/img/bathroom/');//this will be created inside public folder
   $filename = round(microtime(true) * 1000) . "." .$image->getClientOriginalExtension();

  //upload file
  $this->uploadFile($image,$destinationPath,$filename,300,300);

//put your code to Save In Database
//just save the $filename in the db. 

//put your return statements here    


}

    


public function  uploadFile($file,$destinationPath,$filename,$height=null,$width=null){
    
//create folder if does not exist
if (!File::exists($destinationPath)){
   File::makeDirectory($destinationPath, 0777, true, true);
}
    
//Resize the image before upload using Image        Intervention
            
if($height!=null && $width!=null){
   $image_resize = Image::make($file->getRealPath());
   $image_resize->resize($width, $height);
   //Upload the resized image to the project path
   $image_resize->save($destinationPath.$filename);
}else{
     //upload the original image without resize. 
     $file->move($destinationPath,$filename);
     }
}

If you anyways want to use the Storage Facade,I have modified your code by using Image->resize()->encode() before using the Storage::put(). Please see if the following code works. (Sorry, I got not time to test)

public function addPicture(Request $request, $id)
{
  $bathroom = Bathroom::withTrashed()->findOrFail($id);
  $validatedData = Validator::make($request->all(), [
    'afbeelding' =>'required|image|dimensions:min_width=400,min_height=400']);
if($validatedData->fails())
{
    return Response()->json([
        "success" => false,
        "errors" => $validatedData->errors()
    ]);
}
if ($file = $request->file('afbeelding')) {
    $img = Image::make($file);
    $img->resize(3000, 3000, function ($constraint) {
        $constraint->aspectRatio();
        $constraint->upsize();
    });
    //Encode the image if you want to use Storage::put(),this is important step
    $img->encode('jpg',100);//default quality is 90,i passed 100
    $uid = Str::uuid();
    $fileName = Str::slug($bathroom->name . $uid).'.jpg';

    $this->createImage($img, 3000, "high", $bathroom->id, $fileName);
    $this->createImage($img, 1000, "med", $bathroom->id, $fileName);
    $this->createImage($img, 700, "thumb", $bathroom->id, $fileName);
    $this->createImage($img, 400, "small", $bathroom->id, $fileName);

    $picture = new Picture();
    $picture->url = '-';
    $picture->priority = '99';
    $picture->alt = Str::limit($bathroom->description,100);
    $picture->margin = 0;
    $picture->path = $fileName;
    $picture->bathroom_id = $id;
    $picture->save();

    return Response()->json([
        "success" => true,
        "image" => asset('/storage/img/bathroom/'.$id.'/small/'.$fileName),
        "id" => $picture->id
    ]);
}
return Response()->json([
    "success" => false,
    "image" => ''
]);
}
  public function createImage($img, $size, $quality, $bathroomId,$fileName){
$img->resize($size, $size, function ($constraint) {
    $constraint->aspectRatio();
    $constraint->upsize();
});
Storage::put(  $this->getUploadPath($bathroomId, $fileName, $quality), $img);

}
public function  getUploadPath($bathroom_id, $filename, $quality ='high'){
$returnPath = asset('/storage/img/bathroom/'.$bathroom_id.'/'.$quality.'/'.$filename);
return $returnPath; //changed echo to return

}

Source used: Intervention repo,Github

Also, please note that The put method of Storage works with the Image Intervention output whereas the putFile method works with both the Illuminate\Http\UploadedFile as well as Illuminate\Http\File and instances.

-1
votes

i recomended use features from laravel Storage that's simple for any upload