zoukankan      html  css  js  c++  java
  • PHP上传图片

    Laravel异步上传流程一

    1. 产生异步的请求
    2. 请求得有一个相应的方法(需要返回值,返回内容:图片的路径;在此不需要进行数据表的交互)
    3. 当异步请求获取到相应之后需要存储图片的地址(但是又没必要给用户看地址,可以使用隐藏域的方式进行存储)
    4. 当用户提交表单的时候,顺带提交隐藏域的地址

    Laravel 实现上传处理方法

    在 laravel 项目中除了在上传的时候可以使用 move 和 store 方法【都是 request 实例封装的】之外,还可以使用高级的上传文件保存方法 (由 storage 门面提供的)

    Storage 门面在使用的时候需要的注意事项:

    • 在 storage 门面中,有一个 “磁盘” 的概念,“磁盘” 一共有三种:本地磁盘,公共磁盘,第三方磁盘;“磁盘” 实质上就是一个目录
    • 本地磁盘 (local 磁盘),这些文件存放在 local 磁盘中的文件是不能被浏览器访问到的,存储在其中的文件一般都是项目的 php 代码自身使用!(磁盘位置位于 / Storage/app)
    • 公共磁盘 (public 磁盘),存储在该磁盘的文件一般是允许浏览器进行访问的。【磁盘位置位于:/Storage/app/public】
    • 第三方磁盘:驱动形式的一种,允许开发者将文件上传到第三方的服务器上。
    • 磁盘存在一个配置文件,位置 /config/filesystems.php

    默认情况下,浏览器是无法访问到 public 磁盘目录的,但是其又想让浏览器访问,所以需要做一个 “软链接的 “的操作”

    php artisan storage:link
    

    相当于快捷方式

    当软链接创建好之后,Public 磁盘中的内容会被同步到 /public/storage/ 下

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

    Storage::disk(磁盘名)->put(文件名,文件内容);
    

    异步请求回调处理

    在 HTML 代码中添加隐藏域

    <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 数组:

      • zgldhQiniuStorageQiniuFilesystemServiceProvider::class,
        

    Laravel存储用户上传图片的方法二

    本项目中,我们不止上传头像需要用到『图片上传功能』,在后面发布帖子功能中,我们也将会允许用户上传图片,所以此处我们需要预先设计一下图片上传相关的逻辑,我们可以将『图片上传』核心操作做成一个工具类(注意顶部 use IlluminateSupportStr;):

    app/Handlers/ImageUploadHandler.php

    <?php
    
    namespace AppHandlers;
    
    use  IlluminateSupportStr;
    
    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 thinkfacadeFilesystem;
    
    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=" 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=" 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 	hink
    esponseJson
         */
        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);
            }
        });
    
  • 相关阅读:
    jQuery使用手册
    数据结构排序算法总结(转)
    VS2008升级激活码
    用VS2005建立解决方案
    backgroundposition 用法详细介绍
    CSS布局口诀,学ccs不再难
    Web.Config文件中SQLServerExpress数据库连接配置解释(转)
    css
    2011,我来了!
    Ajax验证用户名是否存在
  • 原文地址:https://www.cnblogs.com/wxvirus/p/12894272.html
Copyright © 2011-2022 走看看