Làm thế nào để lấy URL của tệp bằng cách sử dụng mặt tiền Storage trong laravel 5?


82

Tôi đã thử nghiệm bằng cách sử dụng tích hợp Flysystem mới với Laravel 5. Tôi đang lưu trữ các đường dẫn 'bản địa hóa' đến DB và nhận được mặt tiền Storage để hoàn thành đường dẫn. Ví dụ tôi lưu trữ screenshots/1.jpgvà sử dụng

Storage::disk('local')->get('screenshots/1.jpg')

hoặc là

Storage::disk('s3')->get('screenshots/1.jpg') 

Tôi có thể lấy cùng một tệp trên các đĩa khác nhau.

get truy xuất nội dung tệp, nhưng tôi hy vọng sử dụng nó trong các chế độ xem của mình như sau:

<img src="{{ Storage::path('screenshots/1.jpg') }}" />

nhưng đường dẫn hoặc bất cứ thứ gì có thể truy xuất đường dẫn đầy đủ đều không khả dụng (theo như tôi thấy). Vậy làm thế nào tôi có thể trả lại đường dẫn đầy đủ? Hoặc, tôi tự hỏi liệu đây có phải là do thiết kế? Nếu vậy, tại sao tôi không thể có được con đường đầy đủ? Hoặc, tôi đang đi về điều này hoàn toàn sai cách?


1
Bạn đang yêu cầu url chứ không phải đường dẫn.
Adam

Câu trả lời:


54

Chỉnh sửa: Giải pháp cho L5.2 +

Có một giải pháp tốt hơn và đơn giản hơn.

Sử dụng Storage::url($filename)để lấy đường dẫn / URL đầy đủ của một tệp nhất định. Lưu ý rằng bạn cần đặt S3làm hệ thống tệp lưu trữ của mình trong config/filesystems.php:'default' => 's3'

Tất nhiên, bạn cũng có thể làm Storage::disk('s3')->url($filename)theo cách tương tự.

Như bạn có thể thấy trong config/filesystems.phpđó cũng có một thông số 'cloud' => 's3'được xác định, đề cập đến hệ thống tệp Cloud. Trong trường hợp bạn muốn lưu trữ thư mục lưu trữ trong máy chủ cục bộ nhưng truy xuất / lưu trữ một số tệp trong sử dụng đám mây Storage::cloud(), tức là cũng có các phương pháp hệ thống tệp tương tự Storage::cloud()->url($filename).

Tài liệu của Laravel không đề cập đến phương pháp này, nhưng nếu bạn muốn biết thêm về nó, bạn có thể kiểm tra mã nguồn của nó tại đây .


đẹp! đây là một phương pháp mới , nhưng tôi rất vui vì nó đã ở đây ngay bây giờ! Lớp Storage có hoạt động trong các khung nhìn theo mặc định không? Nếu vậy, sẽ đánh dấu đây là câu trả lời đúng.
daviestar

Đúng! nó hoạt động trong chế độ xem của bạn theo mặc định, vì vậy bạn không phải lo lắng về điều đó.
Pere Joan Martorell

5
Điều này dành cho L5.2 +
daviestar

153

Đường dẫn đến đĩa Lưu trữ của bạn sẽ là:

$storagePath  = Storage::disk('local')->getDriver()->getAdapter()->getPathPrefix()

Tôi không biết giải pháp nào ngắn hơn cho điều đó ...

Bạn có thể chia sẻ $ storagePath với Chế độ xem của mình và sau đó chỉ cần gọi

$storagePath."/myImg.jpg";

Đây là giải pháp hoàn hảo để lấy đường dẫn của thư mục lưu trữ công cộng. Cảm ơn!
David

14
Một cách khác là sử dụng applyPathPrefixnhư thế này:Storage::disk('local')->getDriver()->getAdapter()->applyPathPrefix('myImg.jpg');
Maxim Lanin

3
@maximLanin: Bằng cách nào đó nếu bạn sao chép ví dụ của mình, ví dụ cuối cùng (applyPathPrefix) có một ký tự kỳ lạ giữa h và P (path * Prefix). Nếu bạn sao chép dán, bạn sẽ gặp lỗi. Người đầu tiên applyPathPrefixbạn có thể sao chép. Rất lạ. (bạn có thể kiểm tra nó bằng cách nhấp đúp vào tên phương thức cuối cùng trong ví dụ của bạn.
Maurice

3
getDriver()là không cần thiết. Đơn giản là Storage::disk('local')->getAdapter()->getPathPrefix()sẽ hoạt động tốt.
RA.

6
Có lẽ tốt để biết rằng kể từ khi Laravel 5.4 có một phương pháp mới, đơn giản Storage::path, xem câu trả lời Bilal của
Marten Koetsier

69

Phương thức này tồn tại kể từ Laravel 5.4, bạn có thể lấy nó bằng cách:

$path = Storage::disk('public')->path($filename);

1
Hoạt động giống như một sự quyến rũ trong Laravel 5.6. Nếu ai đó thắc mắc về việc này trong API, đây là nó: laravel.com/api/5.6/Illuminate/Filesystem/...
Thiên thần Santiago Jaime Zavala

1
Theo như tôi thấy, phương pháp này tồn tại từ năm Laravel 5.4 ( laravel.com/api/5.4/Illuminate/Filesystem/... )
Marten Koetsier

Cả hai liên kết trong hai bình luận trên đều đã chết.
dotNET

9

Đây là cách tôi làm cho nó hoạt động - chuyển đổi giữa s3 và đường dẫn thư mục cục bộ bằng một biến môi trường, chuyển đường dẫn đến tất cả các chế độ xem.

Trong .env:

APP_FILESYSTEM=local or s3
S3_BUCKET=BucketID

Trong config / filesystems.php:

'default' => env('APP_FILESYSTEM'),

Trong app/Providers/AppServiceProvider:

public function boot()
{
    view()->share('dynamic_storage', $this->storagePath());
}

protected function storagePath()
{
    if (Storage::getDefaultDriver() == 's3') {
        return Storage::getDriver()
                ->getAdapter()
                ->getClient()
                ->getObjectUrl(env('S3_BUCKET'), '');
    }

    return URL::to('/');
}

1
Việc sử dụng Bộ nhớ s3 như mô tả đã tạo ra lỗi cho tôi. Vì vậy, tôi sửa đổi các ví dụ để này return Storage::disk('s3')->getDriver()->getAdapter()->getClient()->getObjectUrl(env('S3_BUCKET'), '').'/';
Lionel Morrison

5

Đầu tiên, hãy lấy url / liên kết của tệp rồi đến đường dẫn, như bên dưới:

$url = Storage::disk('public')->url($filename);
$path = public_path($url);

5

Nếu bạn chỉ muốn hiển thị đường dẫn lưu trữ (đĩa), hãy sử dụng cái này:

Storage::disk('local')->url('screenshots/1.jpg'); // storage/screenshots/1.jpg
Storage::disk('local')->url(''): // storage

Ngoài ra, nếu bạn quan tâm, tôi đã tạo một gói ( https://github.com/fsasvari/laravel-uploadify ) chỉ dành cho Laravel để bạn có thể sử dụng tất cả các trường đó trên các trường Eloquent model:

$car = Car::first();

$car->upload_cover_image->url();
$car->upload_cover_image->name();
$car->upload_cover_image->basename();
$car->upload_cover_image->extension();
$car->upload_cover_image->filesize();

4

Chà, cách đây vài tuần, tôi đã đưa ra một câu hỏi rất tương tự ( Lấy url CDN từ tệp tải lên qua Bộ nhớ ): Tôi muốn url CDN hiển thị hình ảnh trong chế độ xem của tôi (như bạn đang yêu cầu).

Tuy nhiên, sau khi xem xét gói API, tôi xác nhận rằng không có cách nào thực hiện tác vụ này. Vì vậy, giải pháp của tôi là tránh sử dụng flysystem. Trong trường hợp của tôi, tôi cần chơi với RackSpace. Vì vậy, cuối cùng quyết định tạo gói sử dụng của tôi và tạo gói lưu trữ của riêng tôi bằng cách sử dụng SDK PHP cho OpenStack .

Bằng cách này, bạn có toàn quyền truy cập vào các chức năng mà bạn cần getPublicUrl()để lấy URL công khai từ vùng chứa cdn:

/** @var DataObject $file */
$file = \OpenCloud::container('cdn')->getObject('screenshots/1.jpg');

// $url:  https://d224d291-8316ade.ssl.cf1.rackcdn.com/screenshots/1.jpg
$url = (string) $file->getPublicUrl(UrlType::SSL);

Kết luận, nếu cần phải đưa dịch vụ lưu trữ lên một cấp độ khác, thì flysystemvẫn chưa đủ. Vì localmục đích, bạn có thể thử giải pháp của @ nXu


3

Nếu bạn cần URL tuyệt đối của tệp, hãy sử dụng mã dưới đây:

$file_path = \Storage::url($filename);
$url = asset($file_path);
// Output: http://example.com/storage/filename.jpg

2

Phương thức lưu trữ:

public function upload($img){
   $filename = Carbon::now() . '-' .  $img->getClientOriginalName();
   return Storage::put($filename, File::get($img)) ? $filename : '';
}

Lộ trình:

 Route::get('image/{filename}', [
        'as'   => 'product.image',
        'uses' => 'ProductController@getImage',
    ]);

Bộ điều khiển:

 public function getImage($filename)
    {
        $file = Storage::get($filename);

        return new Response($file, 200);
    }

Lượt xem:

 <img src="{{ route('product.image', ['filename' => $yourImageName]) }}" alt="your image"/>

tại sao ai đó sẽ làm điều đó, tại sao sử dụng s3 sau đó broxy nó trong máy chủ web !!
Shady Keshk

2

Một giải pháp khác mà tôi tìm thấy là:

Storage::disk('documents')->getDriver()->getConfig()->get('url')

Sẽ trả về url với đường dẫn cơ sở của tài liệu Storage


1

Hãy xem phần này: Cách sử dụng storage_path () để xem hình ảnh trong laravel 4 . Điều tương tự cũng áp dụng cho Laravel 5:

Bộ nhớ dành cho hệ thống tệp và phần lớn của nó không thể truy cập vào máy chủ web. Giải pháp được khuyến nghị là lưu trữ hình ảnh ở đâu đó trong thư mục chung (là thư mục gốc của tài liệu), public/screenshots/chẳng hạn. Sau đó, khi bạn muốn hiển thị chúng, hãy sử dụng asset('screenshots/1.jpg').


Tôi cố gắng để thiết lập một 'đĩa' là thư mục công cộng của tôi khi phát triển và s3 khi sống
daviestar

Nó không thực sự quan trọng, Storage::path()trả về đường dẫn của tệp trên máy chủ của bạn, nhưng bạn cần một URL đến nó và máy chủ web chỉ có thể phục vụ các tệp từ gốc tài liệu của bạn <project>/public. Tạo các thư mục của bạn bên trong nó và sử dụng url()hoặc asset()trong các mẫu lưỡi dao.
nXu

2
Storage::path()không tồn tại, tôi muốn nó mặc dù vậy
daviestar

Được rồi, tôi đã hiểu lầm, xin lỗi. Những gì tôi muốn làm, vẫn giống nhau: lưu đường dẫn đầy đủ đến DB, có thể là cục bộ hoặc s3. Khi tải lên / tạo hình ảnh, chỉ cần kiểm tra getenv('debug')và quyết định sử dụng cái nào.
nXu

Tôi đã cố gắng tránh lưu toàn bộ con đường nhưng có lẽ đó là cách hợp lý nhất để đi.
daviestar

1

Trong trường hợp của tôi, tôi đã tạo phương thức riêng cho các tệp cục bộ, trong tệp này: src / Illuminate / Filesystem / FilesystemAdapter.php

    /**
 * Get the local path for the given filename.
 * @param $path
 * @return string
 */
public function localPath($path)
{
    $adapter = $this->driver->getAdapter();
    if ($adapter instanceof LocalAdapter) {
        return $adapter->getPathPrefix().$path;
    } else {
        throw new RuntimeException('This driver does not support retrieving local path');
    }
}

sau đó, tôi tạo pull request tới framework, nhưng nó vẫn chưa được hợp nhất vào main core: https://github.com/laravel/framework/pull/13605 Có thể ai đó hợp nhất cái này))


0

công việc này cho tôi vào năm 2020 tại laravel 7

        $image_resize = Image::make($image->getRealPath());
        $image_resize->resize(800,600);
        $image_resize->save(Storage::disk('episodes')->path('') . $imgname);

vì vậy bạn có thể sử dụng nó như thế này

echo Storage::disk('public')->path('');
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.