Laravel 5 - วิธีเข้าถึงภาพที่อัพโหลดในพื้นที่เก็บข้อมูลภายใน View


172

ฉันอัพโหลดรูปประจำตัวของผู้ใช้ในที่จัดเก็บ Laravel แล้ว ฉันจะเข้าถึงพวกเขาและทำให้พวกเขาในมุมมองได้อย่างไร?

เซิร์ฟเวอร์กำลังชี้การร้องขอทั้งหมดไปยัง/publicดังนั้นฉันจะแสดงพวกเขาได้อย่างไรถ้าพวกเขาอยู่ใน/storageโฟลเดอร์?

คำตอบ:


349

ที่ดีที่สุดวิธีการคือการสร้างการเชื่อมโยงสัญลักษณ์เช่น @SlateEntropy อย่างดีชี้ให้เห็นในคำตอบดังต่อไปนี้ เพื่อช่วยในเรื่องนี้ตั้งแต่เวอร์ชั่น 5.3 Laravel มีคำสั่งซึ่งทำให้ง่ายอย่างไม่น่าเชื่อ:

php artisan storage:link

ที่สร้าง symlink จากpublic/storageไปstorage/app/publicสำหรับคุณและนั่นคือทั้งหมดที่มีให้มัน ตอนนี้ไฟล์ใด ๆ ใน/storage/app/publicสามารถเข้าถึงได้ผ่านลิงค์เช่น:

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

หากด้วยเหตุผลใดก็ตามคุณไม่สามารถสร้างลิงก์สัญลักษณ์ (บางทีคุณอยู่ในโฮสติ้งที่ใช้ร่วมกัน ฯลฯ ) หรือคุณต้องการปกป้องไฟล์บางไฟล์ที่อยู่ด้านหลังตรรกะการควบคุมการเข้าถึงบางอย่างก็มีทางเลือกอื่น ๆ ทำหน้าที่ภาพ ตัวอย่างเช่นเส้นทางปิดง่ายเช่นนี้:

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

ตอนนี้คุณสามารถเข้าถึงไฟล์ได้เช่นเดียวกับที่คุณมี symlink:

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

หากคุณใช้ไลบรารีภาพการแทรกแซงคุณสามารถใช้responseวิธีการที่สร้างขึ้นภายในเพื่อทำให้สิ่งต่าง ๆ กระชับยิ่งขึ้น:

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

คำเตือน

โปรดทราบว่าด้วยการให้บริการไฟล์ด้วยตนเองคุณอาจได้รับโทษปรับประสิทธิภาพเนื่องจากคุณต้องผ่านวงจรชีวิตของคำขอ Laravel ทั้งหมดเพื่ออ่านและส่งเนื้อหาไฟล์ซึ่งช้ากว่าเซิร์ฟเวอร์ HTTP อย่างมาก


นั่นดูดีนะ ฉันอยากถามอีกหนึ่งคำถาม แนะนำให้เก็บไฟล์เช่นอวตารนิ้วหัวแม่มือและอื่น ๆ (ไฟล์ที่อัพโหลดจากผู้ใช้) ไว้ในที่เก็บหรือไม่?
TadeášJílek

5
คุณสามารถจัดเก็บได้ทุกที่ที่คุณต้องการยกเว้นว่าเป็นไฟล์ส่วนตัวฉันคิดว่าคุณควรเก็บไว้ในpublicไดเรกทอรี วิธีนี้คุณจะหลีกเลี่ยงค่าใช้จ่ายในการเขียนการตอบสนองภาพที่สามารถจัดการได้เร็วขึ้นโดยเซิร์ฟเวอร์ HTTP
Bogdan

2
โดยส่วนตัวฉันจะไม่เก็บไฟล์ผู้ใช้ในโฟลเดอร์สาธารณะฉันพบสิ่งที่เป็นระเบียบและจัดการได้มากขึ้นเมื่อใช้โฟลเดอร์เก็บข้อมูลสำหรับการจัดเก็บ
SlateEntropy

2
ฉันจะไม่แนะนำอย่างใดอย่างหนึ่งเพราะคุณเพิ่มการโหลด Laravel อีกครั้งและ / หรือใช้ประโยชน์จาก PHP เพื่ออ่านแต่ละภาพ การใช้ symlink ตามที่อธิบายโดย CmdSft จะเร็วขึ้นมาก
user1960364

4
@ user1960364 นั่นคือเหตุผลที่ย่อหน้าสุดท้ายขอแนะนำให้ใช้วิธี symlink แต่คำตอบเองแม้ว่าจะไม่ใช่ทางออกที่ดีที่สุดจากจุดยืนด้านประสิทธิภาพ แต่ก็ยังใช้ได้และอาจเป็นวิธีเดียวสำหรับผู้ที่ใช้งานแอพบนเซิร์ฟเวอร์ที่ใช้ร่วมกันซึ่ง symlink อาจเป็นไปไม่ได้ในการตั้งค่า คำตอบยังแสดงวิธีที่คุณสามารถให้บริการไฟล์โดยใช้โปรแกรมหากมีความจำเป็นเกิดขึ้นบางทีอาจเป็นการให้บริการไฟล์ที่เข้ารหัสเช่นที่ถูกถามในคำถามนี้
Bogdan

53

ทางเลือกหนึ่งคือการสร้างลิงค์สัญลักษณ์ระหว่างโฟลเดอร์ย่อยในไดเรกทอรีจัดเก็บข้อมูลและไดเรกทอรีสาธารณะ

ตัวอย่างเช่น

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

นี่เป็นวิธีที่ใช้โดยEnvoyerซึ่งเป็นผู้จัดการการปรับใช้ที่สร้างโดย Taylor Otwell ผู้พัฒนา Laravel


ฉันค่อนข้างใหม่สำหรับเรื่องนี้ จำเป็นต้องเรียกใช้บนเทอร์มินัลหรือกำหนดไว้ในไฟล์ปรับแต่งที่อื่นใน laravel หรือไม่?
Gaurav Mehta

ใช่คุณต้องเรียกใช้งานผ่านทางบรรทัดคำสั่ง มันจะต้องมีการติดตั้งทุกที่ที่คุณปรับใช้แอพ
SlateEntropy

สำหรับผู้ใช้ Windows ต่อไปนี้เป็นเครื่องมือแบบสแตนด์อโลนหากคุณไม่ต้องการใช้ CMD: github.com/amd989/Symlinker#downloads
David

3
คำถามที่ถามถึงวิธีการแสดงรูปประจำตัวผู้ใช้ที่จัดเก็บในที่storageสาธารณะโดยทั่วไปรูปประจำตัวไม่ต้องการการควบคุมการเข้าถึงใด ๆ หากไม่จำเป็นต้องมีการรักษาความปลอดภัยโดยใช้มิดเดิลแวร์หรือเส้นทางใด ๆ เป็นทรัพยากรของคุณ นอกจากนี้ยังควรสังเกตตั้งแต่ Laravel 5.2 มีไฟล์ "ดิสก์" แยกต่างหากสำหรับไฟล์สาธารณะ ( laravel.com/docs/5.2/filesystem ) โดยใช้ symlinks
SlateEntropy

6
มีคำสั่งของช่างฝีมือที่จะทำสิ่งนี้ใน Laravel 5.3: $ php คลังเก็บของช่างฝีมือ: link
Phil

22

ตามเอกสาร Laravel 5.2 ไฟล์ที่เข้าถึงได้ของคุณควรอยู่ในไดเรกทอรี

storage/app/public

เพื่อให้พวกเขาสามารถเข้าถึงได้จากเว็บคุณควรสร้างการเชื่อมโยงสัญลักษณ์จากไปpublic/storagestorage/app/public

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

ตอนนี้คุณสามารถสร้าง URL ในไฟล์ดูโดยใช้เครื่องมือช่วยเหลือ:

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


13

ก่อนอื่นคุณต้องสร้างลิงค์สัญลักษณ์สำหรับไดเร็กทอรีหน่วยเก็บข้อมูลโดยใช้คำสั่ง artisan

php artisan storage:link

จากนั้นในมุมมองใด ๆ คุณสามารถเข้าถึงภาพของคุณผ่านตัวช่วย url เช่นนี้

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

4

เป็นการดีที่จะบันทึกอิมเมจและเอกสารส่วนตัวทั้งหมดในไดเรกทอรีจัดเก็บจากนั้นคุณจะสามารถควบคุมไฟล์อีเธอร์ได้อย่างสมบูรณ์คุณสามารถอนุญาตให้ผู้ใช้บางประเภทเข้าถึงไฟล์หรือ จำกัด

จัดทำเส้นทาง / เอกสารและชี้ไปที่วิธีการควบคุม:

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

เมื่อคุณจะกดlocalhost:8000/docsไฟล์จะถูกดาวน์โหลดหากมีอยู่

ไฟล์จะต้องอยู่ในroot/storage/app/users/documentsไดเรกทอรีตามรหัสด้านบนซึ่งผ่านการทดสอบLaravel 5.4แล้ว


4

หากคุณต้องการโหลดอิมเมจส่วนตัวจำนวนน้อยคุณสามารถเข้ารหัสอิมเมจเป็น base64 และ echo ให้เป็น<img src="{{$image_data}}">โดยตรง:

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

ฉันพูดถึงความเป็นส่วนตัวเพราะคุณควรใช้วิธีการเหล่านี้หากคุณไม่ต้องการจัดเก็บภาพที่สาธารณชนสามารถเข้าถึงได้ผ่าน URL แต่คุณต้องใช้วิธีมาตรฐานเสมอ (ที่เก็บลิงก์ / โฟลเดอร์สาธารณะและแสดงรูปภาพด้วยเซิร์ฟเวอร์ HTTP)

ระวังการเข้ารหัสให้base64()มีด้านที่สำคัญสองด้าน:

  1. สิ่งนี้จะเพิ่มขนาดภาพประมาณ ~ 30%
  2. คุณรวมขนาดรูปภาพทั้งหมดไว้ในคำขอเดียวแทนที่จะโหลดในรูปแบบขนานนี่ไม่ควรเป็นปัญหาสำหรับภาพขนาดเล็กบางภาพ แต่สำหรับภาพจำนวนมากหลีกเลี่ยงการใช้วิธีนี้

2

หากคุณใช้ php อยู่โปรดใช้ฟังก์ชั่น symlink ของ php ดังนี้:

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

เปลี่ยนชื่อผู้ใช้และชื่อโครงการเป็นชื่อที่ถูกต้อง


1

ไม่มีชื่อไซต์

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

หากคุณต้องการเพิ่มชื่อไซต์ให้เป็นตัวอย่างเพื่อผนวกเข้ากับ api JSON felids

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

0

หากคุณเป็นเช่นฉันและคุณอย่างใดมีเส้นทางไฟล์เต็ม (ฉันได้บาง glob () จับคู่รูปแบบบนภาพถ่ายที่จำเป็นดังนั้นผมจึงสวยมากจบลงด้วยเส้นทางไฟล์เต็ม) และการตั้งค่าการจัดเก็บข้อมูลของคุณมีการเชื่อมโยงกัน (เช่นดังกล่าวว่าเส้นทางของคุณ มีสตริงstorage/app/public/) จากนั้นคุณสามารถใช้แฮ็คสกปรกของฉันด้านล่าง: 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

หากดิสก์ 'local' ไม่ทำงานสำหรับคุณให้ลองทำดังนี้:

  1. เปลี่ยนท้องถิ่นเป็นสาธารณะใน'default' => env('FILESYSTEM_DRIVER', 'public'),จากproject_folder/config/filesystem.php
  2. ล้างแคชการกำหนดค่า php artisan config:clear
  3. จากนั้นสร้างลิงค์ sym php artisan storage:link

ในการรับ URL ของภาพที่อัปโหลดคุณสามารถใช้สิ่งนี้ Storage::url('iamge_name.jpg');

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.