PHP上傳圖片

Laravel異步上傳流程一

  1. 產生異步的請求
  2. 請求得有一個相應的方法(須要返回值,返回內容:圖片的路徑;在此不須要進行數據表的交互)
  3. 當異步請求獲取到相應以後須要存儲圖片的地址(可是又不必給用戶看地址,可使用隱藏域的方式進行存儲)
  4. 當用戶提交表單的時候,順帶提交隱藏域的地址

Laravel 實現上傳處理方法

在 laravel 項目中除了在上傳的時候可使用 move 和 store 方法【都是 request 實例封裝的】以外,還可使用高級的上傳文件保存方法 (由 storage 門面提供的)javascript

Storage 門面在使用的時候須要的注意事項:php

  • 在 storage 門面中,有一個 「磁盤」 的概念,「磁盤」 一共有三種:本地磁盤,公共磁盤,第三方磁盤;「磁盤」 實質上就是一個目錄
  • 本地磁盤 (local 磁盤),這些文件存放在 local 磁盤中的文件是不能被瀏覽器訪問到的,存儲在其中的文件通常都是項目的 php 代碼自身使用!(磁盤位置位於 / Storage/app)
  • 公共磁盤 (public 磁盤),存儲在該磁盤的文件通常是容許瀏覽器進行訪問的。【磁盤位置位於:/Storage/app/public】
  • 第三方磁盤:驅動形式的一種,容許開發者將文件上傳到第三方的服務器上。
  • 磁盤存在一個配置文件,位置 /config/filesystems.php

默認狀況下,瀏覽器是沒法訪問到 public 磁盤目錄的,可是其又想讓瀏覽器訪問,因此須要作一個 「軟連接的 「的操做」html

php artisan storage:link

至關於快捷方式java

當軟連接建立好以後,Public 磁盤中的內容會被同步到 /public/storage/ 下laravel

Storage 門面的通用文件保存方法:ajax

Storage::disk(磁盤名)->put(文件名,文件內容);

異步請求回調處理

在 HTML 代碼中添加隱藏域thinkphp

<input type="hidden" name="avatar" value="">

經過回調將返回的 path 寫入隱藏域後端

使用七牛雲存儲存儲文件

七牛:一家提供各類網絡服務的運營商,其性質相似於阿里雲數組

作到代碼與資源分離瀏覽器

緣由:

  1. 在後期維護網站的也比較方便;
  2. 資源分離以後能夠減輕代碼服務器的壓力;
  3. 如何將資源分離和 CDN (content delivery network 內容分發網絡) 配合起來用,對於 bat 之類的大公司來講 1 年可以生下來的成本至少 7 位數以上;

註冊七牛帳號後建立後期須要的對象存儲實例 (不用充錢,每個月免費 10G 空間, 20G 的流量)

  • 選擇對象存儲

  • 新建空間:本身在哪一個區域選擇哪一個存儲區域

  • 下載七牛的代碼依賴庫

    • composer require zgldh/qiniu-laravel-storage
    • 配置 filesystems.php:

    • 'qiiniu' => [
                'driver' => 'qiniu',
                'domains'=> [
                    'default'   => 'xxxx.com1.z0.glb.clouddn.com',  // 你的七牛域名
                    'https'     => '',
                    'custom'    => ''
                ],
                'access_key'    => '',  // AK
                'secret_key'    => '',  // SK
                'bucket'        => '',  // 磁盤名字
                'notify_url'    => '',  // 持久化處理
                'access'        => 'public',    // 空間訪問控制
            ],
    • 添加 providers 數組:

    • zgldh\QiniuStorage\QiniuFilesystemServiceProvider::class,

Laravel存儲用戶上傳圖片的方法二

本項目中,咱們不止上傳頭像須要用到『圖片上傳功能』,在後面發佈帖子功能中,咱們也將會容許用戶上傳圖片,因此此處咱們須要預先設計一下圖片上傳相關的邏輯,咱們能夠將『圖片上傳』核心操做作成一個工具類(注意頂部 use Illuminate\Support\Str;):

app/Handlers/ImageUploadHandler.php

<?php

namespace App\Handlers;

use  Illuminate\Support\Str;

class ImageUploadHandler
{
    // 只容許如下後綴名的圖片文件上傳
    protected $allowed_ext = ["png", "jpg", "gif", 'jpeg'];

    public function save($file, $folder, $file_prefix)
    {
        // 構建存儲的文件夾規則,值如:uploads/images/avatars/201709/21/
        // 文件夾切割能讓查找效率更高。
        $folder_name = "uploads/images/$folder/" . date("Ym/d", time());

        // 文件具體存儲的物理路徑,`public_path()` 獲取的是 `public` 文件夾的物理路徑。
        // 值如:/home/vagrant/Code/larabbs/public/uploads/images/avatars/201709/21/
        $upload_path = public_path() . '/' . $folder_name;

        // 獲取文件的後綴名,因圖片從剪貼板裏黏貼時後綴名爲空,因此此處確保後綴一直存在
        $extension = strtolower($file->getClientOriginalExtension()) ?: 'png';

        // 拼接文件名,加前綴是爲了增長辨析度,前綴能夠是相關數據模型的 ID 
        // 值如:1_1493521050_7BVc9v9ujP.png
        $filename = $file_prefix . '_' . time() . '_' . Str::random(10) . '.' . $extension;

        // 若是上傳的不是圖片將終止操做
        if ( ! in_array($extension, $this->allowed_ext)) {
            return false;
        }

        // 將圖片移動到咱們的目標存儲路徑中
        $file->move($upload_path, $filename);

        return [
            'path' => config('app.url') . "/$folder_name/$filename"
        ];
    }
}

咱們將使用 app/Handlers 文件夾來存放本項目的工具類,『工具類(utility class)』是指一些跟業務邏輯相關性不強的類,Handlers 意爲 處理器 ,ImageUploadHandler 意爲圖片上傳處理器,簡單易懂。

`public_path()` 獲取的是 `public` 文件夾的物理路徑。

這裏寫了一個圖片上傳處理類,方便網站各處須要上傳圖片的進行調用

調用呢,成功則返回圖片的地址,開發者接收到圖片的地址後,哪怕是在頁面顯示圖片,或者在表單裏進行添加入庫,都提供了方便。

ThinkPHP6.0版本的上傳圖片操做

基於上面Laravel開發的圖片上傳處理類,我將之進行整改,適合TP6的

use think\facade\Filesystem;

class ImageUploadHandle
{
    // 只容許如下後綴的圖片文件
    protected $allowed_ext = ["png", "jpg", "gif", 'jpeg'];

    /**
     * @param $file
     * @param $folder
     * @param bool $fileas 默認爲false,保存到public目錄下的指定目錄格式下;爲true,保存到public下的指定目錄下
     * @return bool|string
     */
    public function save($file, $folder, $fileas = false)
    {
        if ($file) {
            // 獲取文件後綴
            $extension = strtolower($file->extension());
            // 若是上傳的不是圖片終止操做
            if (!in_array($extension, $this->allowed_ext)) {
                return false;
            }
            try {
                $savename = $fileas == false
                    ? Filesystem::disk('public')->putFile($folder, $file)
                    : Filesystem::disk(
                        'public'
                    )
                        ->putFileAs($folder.'/'.date('Ymd'), $file, $file->getOriginalName());
            } catch (\Exception $e) {
                return $e->getMessage();
            }
            if ($savename) {
                // TP6中獲取圖片路徑的方法
                $path = Filesystem::getDiskConfig('public', 'url').'/'.str_replace('\\', '/', $savename);

                return $path;
            }
        }

        return false;
    }
}

這樣會保存到public/storage/本身定義的目錄

對應的html頁面:

<img src="{$admin_info.avatar|default='/static/admin/img/logo.png'}" alt="選擇並上傳頭像" id="avatar_img" style="width: 140px;height: 140px;left:0;top: 0;border-radius: 50%;"/>
                                               
<input type="file" id="avatar" name="avatar" accept="image/jpg,image/png,image/gif" style="width: 100%;height:100%;opacity: 0;position: absolute;left:0;top: 0;" onchange="uploadImg(this)" />
  • {$admin_info}:這是後端進行查詢單個管理員信息的數組
  • {$admin_info.avatar|default='/static/admin/img/logo.png'}:表明若是這個管理員存在頭像,就顯示本身的頭像,沒有則顯示默認的一個圖片的地址
  • 真正點擊上傳頭像的仍是下面的input中的onchange事件調用uploadImg(this)方法
  • this表明當前html組件input

ajax方法上傳代碼:

function uploadImg(obj) {
        if (obj.value === "") {
            return false;
        }
        let formData = new FormData();
        formData.append("avatar", $(obj)[0].files[0]);
        $.ajax({
            type: "POST",
            url: "/admin/Admin/uploadAvatar",
            data: formData,
            cache: false,
            processData: false,
            contentType: false,
            success: function (data) {
                // 接收返回的圖片地址
                if (data.code === 1) {
                    toastr.success("上傳頭像", data.msg);
                    // 設置圖片路徑爲最新的路徑
                    $("#avatar_img").attr("src", data.data.path);
                    setTimeout(function () {
                        location.href = "/admin/Admin/profile";
                    }, 1000);
                } else {
                    toastr.error(data.msg);
                }
            }
        });
        return false;
    }

FormDatajs的一個東西,經過這個將上傳的文件獲取到並appendformData實例中

而後經過ajax進行圖片上傳

後端處理代碼:

經過依賴注入將Request and ImageUploadHandle進行注入

將文件處理類獲取的返回的圖片地址保存到表中

/**
     * 上傳頭像
     * @param Request $request
     * @param ImageUploadHandle $imageUploadHandle
     * @return \think\response\Json
     */
    public function uploadAvatar(Request $request, ImageUploadHandle $imageUploadHandle)
    {
        if (!$request->isPost() || !$request->isAjax()) {
            return writeJson(config('status.error'), "請求類型不合法");
        }

        $avatar = $request->file('avatar');
        $path   = $imageUploadHandle->save($avatar, 'avatar');

        // 將路徑存儲進入表中
        // 獲取當前用戶id
        $admin_id = session('session_admin.id');
        try {
            $result = $this->adminService->saveAvatar($admin_id, $path);
        } catch (\Exception $e) {
            return writeJson(config('status.error'), $e->getMessage());
        }

        $data = ['path' => $path];

        if ($result) {
            return writeJson(config('status.success'), "頭像上傳成功", $data);
        }

        return writeJson(config('status.error'), "上傳失敗");
    }

上傳結束後,使用js來實現預覽效果:

// 頭像預覽
    $("#avatar").change(function () {
        // 獲取上傳文件對象
        var file = $(this)[0].files[0];
        // 讀取文件URL
        var reader = new FileReader();
        reader.readAsDataURL(file);
        // 閱讀文件完成後觸發的事件
        reader.onload = function () {
            // 讀取的URL結果:this.result
            $("#avatar_img").attr("src", this.result);
        }
    });
相關文章
相關標籤/搜索