Laravel 5 - Làm cách nào để truy cập hình ảnh được tải lên trong bộ lưu trữ trong Chế độ xem?


171

Tôi đã có avatar của người dùng được tải lên trong bộ lưu trữ của Laravel. Làm thế nào tôi có thể truy cập chúng và hiển thị chúng trong một khung nhìn?

Máy chủ đang trỏ tất cả các yêu cầu /public, vậy làm thế nào tôi có thể hiển thị chúng nếu chúng nằm trong /storagethư mục?

Câu trả lời:


349

Cách tiếp cận tốt nhất là tạo ra một liên kết tượng trưng như @SlateEntropy được chỉ ra rất rõ trong câu trả lời dưới đây . Để giải quyết vấn đề này, kể từ phiên bản 5.3, Laravel bao gồm một lệnh giúp việc này cực kỳ dễ thực hiện:

php artisan storage:link

Điều đó tạo ra một liên kết tượng trưng từ public/storageđến storage/app/publiccho bạn và đó là tất cả những gì có trong đó. Bây giờ bất kỳ tập tin trong /storage/app/publiccó thể được truy cập thông qua một liên kết như:

http://somedomain.com/storage/image.jpg

Nếu vì bất kỳ lý do nào, bạn không thể tạo các liên kết tượng trưng (có thể bạn đang sử dụng lưu trữ được chia sẻ, v.v.) hoặc bạn muốn bảo vệ một số tệp đằng sau một số logic kiểm soát truy cập, có một cách khác là có một tuyến đường đặc biệt đọc và Phục vụ hình ảnh. Ví dụ một tuyến đường đóng cửa đơn giản như thế này:

Route::get('storage/{filename}', function ($filename)
{
    $path = storage_path('public/' . $filename);

    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;
});

Bây giờ bạn có thể truy cập các tệp của mình như bạn muốn nếu bạn có một liên kết tượng trưng:

http://somedomain.com/storage/image.jpg

Nếu bạn đang sử dụng Thư viện hình ảnh can thiệp, bạn có thể sử dụng responsephương thức tích hợp sẵn để làm cho mọi thứ ngắn gọn hơn:

Route::get('storage/{filename}', function ($filename)
{
    return Image::make(storage_path('public/' . $filename))->response();
});

CẢNH BÁO

Hãy nhớ rằng bằng cách phục vụ thủ công các tệp bạn đang phải chịu một hình phạt hiệu suất , bởi vì bạn đang trải qua toàn bộ vòng đời yêu cầu của Laravel để đọc và gửi nội dung tệp, chậm hơn đáng kể so với việc máy chủ HTTP xử lý nó.


Điều đó có vẻ tốt. Tôi muốn hỏi thêm một câu nữa. Có nên lưu trữ các tệp như hình đại diện, ngón tay cái và vv (tệp đã tải lên từ người dùng) trong bộ lưu trữ không?
Tadeáš Jílek

5
Bạn có thể lưu trữ chúng bất cứ nơi nào bạn thích, nhưng trừ khi đó là những tệp riêng tư, tôi nghĩ bạn nên lưu trữ chúng trong publicthư mục. Bằng cách này, bạn sẽ tránh được việc phải soạn một phản hồi hình ảnh có thể được xử lý nhanh hơn nhiều bởi máy chủ HTTP.
Bogdan

2
Cá nhân tôi sẽ không lưu trữ các tệp người dùng trong thư mục công cộng, tôi thấy mọi thứ gọn gàng hơn và dễ quản lý hơn khi thư mục lưu trữ được sử dụng để lưu trữ.
SlateEntropy

2
Tôi sẽ không đề xuất một trong hai điều này bởi vì sau đó bạn sẽ thêm chi phí tải lại Laravel và / hoặc tận dụng PHP để đọc từng hình ảnh. Sử dụng một liên kết tượng trưng như được mô tả bởi CmdSft sẽ nhanh hơn nhiều.
dùng1960364

4
@ user1960364 Đó là lý do tại sao đoạn cuối đề nghị mạnh mẽ sử dụng phương pháp liên kết tượng trưng. Nhưng bản thân câu trả lời, mặc dù không phải là giải pháp tốt nhất từ ​​quan điểm hiệu suất, vẫn hợp lệ và có thể là cách tiếp cận duy nhất cho những người chạy ứng dụng trên các máy chủ được chia sẻ, nơi các liên kết tượng trưng có thể không thể thiết lập. Câu trả lời cũng chỉ ra cách bạn có thể phục vụ các tệp theo chương trình nếu có nhu cầu, có thể để phục vụ các tệp được mã hóa như được hỏi trong câu hỏi này .
Bogdan

53

Một tùy chọn sẽ là tạo một liên kết tượng trưng giữa thư mục con trong thư mục lưu trữ và thư mục công cộng.

Ví dụ

ln -s /path/to/laravel/storage/avatars /path/to/laravel/public/avatars

Đây cũng là phương pháp được sử dụng bởi Envoyer , một người quản lý triển khai được xây dựng bởi Taylor Otwell, nhà phát triển của Laravel.


Tôi hơi mới với điều này. Điều này có cần phải được chạy trên thiết bị đầu cuối hoặc được xác định trong một tệp cấu hình ở đâu đó trong laravel không?
Gaurav Mehta

vâng, bạn cần chạy cái này mặc dù dòng lệnh. Nó sẽ cần phải được thiết lập bất cứ nơi nào bạn triển khai ứng dụng.
SlateEntropy

Đối với người dùng Windows, đây là một công cụ độc lập cho điều đó nếu bạn không muốn sử dụng CMD: github.com/amd989/Symlinker#doads
David

3
Câu hỏi hỏi làm thế nào để hiển thị hình đại diện người dùng được lưu trữ storagecông khai, thông thường hình đại diện không yêu cầu bất kỳ loại kiểm soát truy cập nào. Nếu không có bảo mật được yêu cầu sử dụng bất kỳ loại phần mềm trung gian hoặc tuyến đường nào chỉ là một sự lãng phí đối với tài nguyên của bạn. Điều đáng chú ý là vì Laravel 5.2 tồn tại một "đĩa" riêng cho các tệp công khai ( laravel.com/docs/5.2/filesystem ) bằng cách sử dụng liên kết tượng trưng.
SlateEntropy

6
Có một lệnh thủ công để thực hiện việc này trong Laravel 5.3: $ Lưu trữ nghệ nhân php: link
Phil

22

Theo tài liệu của Laravel 5.2, các tệp có thể truy cập công khai của bạn nên được đặt trong thư mục

storage/app/public

Để làm cho chúng có thể truy cập từ web, bạn nên tạo một liên kết tượng trưng từ public/storageđến storage/app/public.

ln -s /path/to/laravel/storage/app/public /path/to/laravel/public/storage

Bây giờ bạn có thể tạo trong chế độ xem URL của mình tới các tệp bằng trình trợ giúp nội dung:

echo asset('storage/file.txt');


13

Trước hết bạn cần tạo một liên kết tượng trưng cho thư mục lưu trữ bằng lệnh artisan

php artisan storage:link

Sau đó, trong bất kỳ chế độ xem nào, bạn có thể truy cập hình ảnh của mình thông qua trình trợ giúp url như thế này.

url('storage/avatars/image.png');

4

Thật tốt khi lưu tất cả các hình ảnh và tài liệu riêng tư trong thư mục lưu trữ, sau đó bạn sẽ có toàn quyền kiểm soát tệp ether, bạn có thể cho phép một số loại người dùng truy cập vào tệp hoặc hạn chế.

Tạo một lộ trình / tài liệu và trỏ đến bất kỳ phương thức điều khiển nào:

public function docs() {

    //custom logic

    //check if user is logged in or user have permission to download this file etc

    return response()->download(
        storage_path('app/users/documents/4YPa0bl0L01ey2jO2CTVzlfuBcrNyHE2TV8xakPk.png'), 
        'filename.png',
        ['Content-Type' => 'image/png']
    );
}

Khi bạn nhấn localhost:8000/docstập tin sẽ được tải xuống nếu có.

Các tập tin phải nằm trong root/storage/app/users/documentsthư mục theo mã trên, điều này đã được thử nghiệm trên Laravel 5.4.


4

Nếu bạn muốn tải một số lượng nhỏ Hình ảnh riêng tư Bạn có thể mã hóa hình ảnh thành base64 và dội lại chúng <img src="{{$image_data}}">trực tiếp:

$path = image.png
$full_path = Storage::path($path);
$base64 = base64_encode(Storage::get($path));
$image_data = 'data:'.mime_content_type($full_path) . ';base64,' . $base64;

Tôi đã đề cập riêng tư vì bạn chỉ nên sử dụng các phương pháp này nếu bạn không muốn lưu trữ hình ảnh có thể truy cập công khai qua url, thay vào đó bạn phải luôn sử dụng cách tiêu chuẩn (lưu trữ liên kết / thư mục công cộng và cung cấp hình ảnh với máy chủ HTTP).

Coi chừng mã hóa để base64()có hai mặt quan trọng:

  1. Điều này sẽ tăng kích thước hình ảnh lên ~ 30%.
  2. Bạn kết hợp tất cả các kích thước hình ảnh trong một yêu cầu, thay vì tải chúng song song, đây không phải là vấn đề đối với một số hình thu nhỏ nhưng đối với nhiều hình ảnh tránh sử dụng phương pháp này.

2

Nếu bạn đang sử dụng php thì chỉ cần sử dụng chức năng symlink của php, như sau:

symlink('/home/username/projectname/storage/app/public', '/home/username/public_html/storage')

thay đổi tên người dùng và tên dự án thành tên đúng.


1

không có tên trang web

{{Storage::url($photoLink)}}

nếu bạn muốn thêm tên trang web vào ví dụ để thêm vào felids JSON của api

 public function getPhotoFullLinkAttribute()
{
    return env('APP_URL', false).Storage::url($this->attributes['avatar']) ;
}

0

Nếu bạn giống như tôi và bạn bằng cách nào đó có đường dẫn tệp đầy đủ (tôi đã thực hiện một số mẫu hình cầu () phù hợp với các ảnh được yêu cầu, thì tôi sẽ kết thúc khá nhiều với đường dẫn tệp đầy đủ) và thiết lập lưu trữ của bạn được liên kết tốt (ví dụ như đường dẫn của bạn có chuỗi storage/app/public/), sau đó bạn có thể sử dụng bản hack bẩn nhỏ của tôi bên dưới: p)

 public static function hackoutFileFromStorageFolder($fullfilePath) {
        if (strpos($fullfilePath, 'storage/app/public/')) {
           $fileParts = explode('storage/app/public/', $fullfilePath);
           if( count($fileParts) > 1){
               return $fileParts[1];
           }
        }

        return '';
    }

0

Nếu đĩa 'cục bộ' không hoạt động cho bạn thì hãy thử điều này:

  1. Thay đổi địa phương thành công khai 'default' => env('FILESYSTEM_DRIVER', 'public'),từproject_folder/config/filesystem.php
  2. Xóa bộ nhớ cache cấu hình php artisan config:clear
  3. Sau đó tạo liên kết sym php artisan storage:link

Để lấy url của hình ảnh được tải lên, bạn có thể sử dụng Storage::url('iamge_name.jpg');

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.