Вмешательство в образ с хранилищем Laravel 5.4

Я использую фасад хранилища для хранения аватара, который отлично работает, но я хочу изменить размер своего изображения, как в предыдущих версиях laravel. Как я могу это сделать? Вот что у меня есть на данный момент (не работает)

  $path   = $request->file('createcommunityavatar');
  $resize = Image::make($path)->fit(300);
  $store  = Storage::putFile('public/image', $resize);
  $url    = Storage::url($store);

Сообщение об ошибке:

  Command (hashName) is not available for driver (Gd).

person wizardzeb    schedule 13.10.2016    source источник
comment
Привет, попробуйте это Image::make($path)-›resize(300, 300);   -  person Vision Coderz    schedule 13.10.2016
comment
Это дало мне ту же ошибку, что и раньше. Command (hashName) is not available for driver (Gd).   -  person wizardzeb    schedule 13.10.2016
comment
Это было решено?   -  person dbr    schedule 13.11.2016
comment
@CriticalTheWizard Замена драйвера на imagick не помогла. Теперь я получаю Command (hashName) is not available for driver (Imagick).   -  person dbr    schedule 13.11.2016


Ответы (10)


Вы пытаетесь передать в putFile неправильный объект. Этот метод ожидает объект File (не изображение).

$path   = $request->file('createcommunityavatar');

// returns \Intervention\Image\Image - OK
$resize = Image::make($path)->fit(300);

// expects 2nd arg - \Illuminate\Http\UploadedFile - ERROR, because Image does not have hashName method
$store  = Storage::putFile('public/image', $resize);

$url    = Storage::url($store);

Хорошо, теперь, когда мы поняли основную причину, давайте исправим код

// returns Intervention\Image\Image
$resize = Image::make($path)->fit(300)->encode('jpg');

// calculate md5 hash of encoded image
$hash = md5($resize->__toString());

// use hash as a name
$path = "images/{$hash}.jpg";

// save it locally to ~/public/images/{$hash}.jpg
$resize->save(public_path($path));

// $url = "/images/{$hash}.jpg"
$url = "/" . $path;

Давайте представим, что вы хотите использовать фасад хранилища:

// does not work - Storage::putFile('public/image', $resize);

// Storage::put($path, $contents, $visibility = null)
Storage::put('public/image/myUniqueFileNameHere.jpg', $resize->__toString());
person Leonid Shumakov    schedule 08.01.2017
comment
Приведенный выше код работает отлично, с одним примечанием: md5($resize->__toString()); всегда возвращает один и тот же хеш для одного и того же файла, что в некоторых случаях может быть проблематичным. В моем решении я заменил это на $now = Carbon::now()->toDateTimeString(); $hash = md5($image->__toString().$now); - person Tomasz Machura; 05.01.2018

Метод put работает с выводом вмешательства изображения. Метод putFile принимает экземпляр Illuminate\Http\File или Illuminate\Http\UploadedFile.

$photo = Image::make($request->file('photo'))
  ->resize(400, null, function ($constraint) { $constraint->aspectRatio(); } )
  ->encode('jpg',80);

Storage::disk('public')->put( 'photo.jpg', $photo);

Приведенный выше код изменяет размер загруженного файла до ширины 400 пикселей, сохраняя соотношение сторон. Затем кодирует в jpg с качеством 80%. Затем файл сохраняется на общедоступный диск. Обратите внимание, что вы должны указать имя файла, а не только каталог.

person Jeffrey    schedule 29.04.2017
comment
Благодарю вас! Очень полезно. Обратите внимание, что вызов encode обязателен, иначе выходные данные будут повреждены. - person Adam; 29.05.2020
comment
И вы также можете использовать его так: Storage::disk('public')->put( $request->file('photo')->hashName(), $photo); - person Adam; 29.05.2020
comment
Действительно полезно для меня - person A.A Noman; 23.09.2020

Использование Laravel 5.8

У меня была аналогичная проблема при попытке прочитать файл изображения с помощью Image, когда этот файл был сохранен и загружен с помощью Storage.
Кроме того все ответы я не был уверен, почему это не работает.


Исключение, когда Image пытался прочитать файл

Intervention\Image\Exception\NotReadableException : невозможно выполнить инициализацию из заданных двоичных данных.

Краткий ответ

Добавление ->encode()решило проблему

http://image.intervention.io/api/encode

Сценарий

В общем, у меня был такой тест

Storage::fake();

$photo = factory(Photo::class)->create();    
$file = \Image::make(
    UploadedFile::fake()->image($photo->file_name, 300, 300)
);

Storage::disk($photo->disk)
    ->put(
        $photo->fullPath(),
        $file
    );

И в контроллере у меня было что-то вроде этого

return \Image::make(
    Storage::disk($photo->disk)
        ->get(
            $photo->fullPath()
        )
)->response();

Решение

После расследования я понял, что любой файл, созданный Image и сохраненный Storage, имеет размер 0 октетов. Посмотрев все решения из этого поста и несколько часов спустя, я заметил, что все используют encode(), но никто не упомянул, что это было именно так. Так что я попробовал, и это сработало.

Если присмотреться еще немного, Image на самом деле кодирует под капотом перед сохранением. https://github.com/Intervention/image/blob/master/src/Intervention/Image/Image.php#L146

Итак, мое решение состояло в том, чтобы просто сделать это

$file = \Image::make(
    \Illuminate\Http\UploadedFile::fake()->image('filename.jpg', 300, 300)
)->encode();

\Storage::put('photos/test.jpg', $file);

можно проверить в Tinker. Будет создано черное изображение

person Clément Baconnier    schedule 28.06.2019
comment
Это то же решение, что и stackoverflow.com/a/43700717/2311074. - person Adam; 29.05.2020
comment
Он также работал при загрузке декодированного файла изображения base64 и сохранении его в хранилище. Без использования функции encode() он не был загружен, когда я использовал Storage::put($file_path, base64_encode($uploadedFile);. Наконец, с помощью изображения вмешательства и функции кодирования это сработало. - person Mycodingproject; 15.07.2020

Самое чистое решение, которое я смог найти — с использованием нативного фасада Storage — заключается в следующем. Я могу подтвердить, что это работает в Laravel 5.7, используя intervention/image версии 2.4.2.

$file = $request->file('avatar');
$path = $file->hashName('public/avatars');
$image = Image::make($file)->fit(300);
Storage::put($path, (string) $image->encode());

$url = Storage::url($path);
person Jesse van der Pluijm    schedule 13.05.2019

Я делаю это так:

  1. Измените размер и сохраните изображение где-нибудь (например, в общей папке).
  2. Создайте новый файл и передайте его функциям файловой системы Laravel (например, putFileAs).
  3. Удалить временный файл вмешательства

Примечание. Конечно, вы можете изменить его в соответствии с вашими потребностями.

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

$image = Image::make($file);

$image->resize(570, 326, function ($constraint) {
    $constraint->aspectRatio();
});

$thumbnail_image_name = pathinfo($file->getClientOriginalName(), PATHINFO_FILENAME).'.'.$file->getClientOriginalExtension();

$image->save(public_path('images/'.$thumbnail_image_name));

$saved_image_uri = $image->dirname.'/'.$image->basename;

//Now use laravel filesystem.
$uploaded_thumbnail_image = Storage::putFileAs('public/thumbnails/'.$portfolio_returned->id, new File($saved_image_uri), $thumbnail_image_name);

//Now delete temporary intervention image as we have moved it to Storage folder with Laravel filesystem.
$image->destroy();
unlink($saved_image_uri);
person Md. Zubaer Ahammed    schedule 05.05.2017
comment
Это работает просто отлично. Это также должен быть принятый ответ. - person Rafik Farhad; 17.10.2019

Я сделал это следующим образом, это просто и без путаницы с путями:

//Get file
$path= $request->file('createcommunityavatar');

// Resize and encode to required type
$img = Image::make($file)->fit(300)->encode('jpg');

//Provide own name
$name = time() . '.jpg';

//Put file with own name
Storage::put($name, $img);

//Move file to your location 
Storage::move($name, 'public/image/' . $name);
person Govind Samrow    schedule 06.02.2019
comment
$path = $request->file() должно быть $file = $request->file(), верно? - person atorscho; 06.06.2019

Обязательно добавьте use Illuminate\Http\File; в начало файла, чтобы это работало, и прочитайте раздел документации Автоматическая потоковая передача.

Предполагается, что вам нужны все файлы JPEG.

$path   = $request->file('createcommunityavatar');
$resize = Image::make($path)->fit(300)->encode('jpg');
$filePath = $resize->getRealPath() . '.jpg';
$resize->save($filePath);
$store  = Storage::putFile('public/image', new File($resize));
$url    = Storage::url($store);

Вот как я делаю это в своем приложении с помощью комментариев

// Get the file from the request
$requestImage = request()->file('image');

// Get the filepath of the request file (.tmp) and append .jpg
$requestImagePath = $requestImage->getRealPath() . '.jpg';

// Modify the image using intervention
$interventionImage = Image::make($requestImage)->resize(125, 125)->encode('jpg');

// Save the intervention image over the request image
$interventionImage->save($requestImagePath);

// Send the image to file storage
$url = Storage::putFileAs('photos', new File($requestImagePath), 'thumbnail.jpg');

return response()->json(['url' => $url]);
person Rob    schedule 13.12.2016
comment
ты имел ввиду $filePath = $resize->getRealPath() . '.jpg'; - person wizardzeb; 14.12.2016
comment
Я попробовал это на новой установке laravel 5.3. *, это работает. Вы пробовали это? - person Rob; 14.12.2016
comment
какой новый файл вы используете здесь? файл http или файл фасадов? - person ClearBoth; 16.02.2017

Попробуйте обновить расширение GD для текущей версии php.

Если это не поможет, попробуйте сохранить образ с измененным размером на локальный диск и использовать Storage::putFile.

Вы можете удалить файл после того, как он будет загружен на ваш путь хранения.

Второй параметр вашего метода putFile — это экземпляр класса Image Intervention. Вам нужно передать это как второй параметр в метод putFile.

$resize->save($absolutePath . 'small/' . $imageName);
person Himanshu Sharma    schedule 15.11.2016

Вы не можете хранить объект \Intervention\Image\Image напрямую в файловой системе Laravel 5. Что вы можете сделать, так это изменить размер изображения из вашего запроса и сохранить его по тому же пути tmp. Затем просто сохраните загруженный (перезаписанный) файл в файловую систему.

Код:

$image  = $request->file('createcommunityavatar');
//resize and save under same tmp path
$resize = Image::make($image)->fit(300)->save();
// store in the filesystem with a generated filename
$store  = $image->store('image', 'public');
// get url from storage
$url    = Storage::url($store);
person Jones03    schedule 11.04.2017

В моем случае ошибка была вызвана вызовом метода hashName для экземпляра изображения.

    //initially
    $image = Image::make(request('image')->getRealPath());
    $filename = $image->hashName();

    //to fix the error
    $image = Image::make(request('image')->getRealPath());
    $filename = request('image')->hashName();
person F KIng    schedule 26.10.2020