dcat-admin

dcat-admin


图片/文件上传

<h1>图片/文件上传</h1> <p><a href="model-form.md">数据表单</a>通过以下的调用来生成图片/文件上传表单,支持本地和云存储的文件上传。上传组件是基于<a href="https://fex.baidu.com/webuploader/">webuploader</a>实现的,具体的使用配置可参考<a href="https://fex.baidu.com/webuploader/document.html">webuploader官方文档</a>。</p> <p>&gt; {tip} 文件或图片上传表单字段请不要在模型中设置<strong>访问器</strong>和<strong>修改器</strong>拼接域名,如有相关需求可参考<a href="#withhost">文件/图片域名拼接</a>。</p> <pre><code class="language-php">$form-&amp;gt;file('file_column'); $form-&amp;gt;image('image_column');</code></pre> <p>&lt;a name=&quot;local&quot;&gt;&lt;/a&gt;</p> <h2>本地上传</h2> <p>先添加存储配置,<code>config/filesystems.php</code> 添加一项<code>disk</code>:</p> <pre><code class="language-php"> 'disks' =&amp;gt; [ ... , 'admin' =&amp;gt; [ 'driver' =&amp;gt; 'local', 'root' =&amp;gt; public_path('uploads'), 'visibility' =&amp;gt; 'public', 'url' =&amp;gt; env('APP_URL').'/uploads', ], ], </code></pre> <p>设置上传的路径为<code>public/uploads</code>(public_path('uploads'))。</p> <p>然后选择上传的<code>disk</code>,打开<code>config/admin.php</code>找到:</p> <pre><code class="language-php"> 'upload' =&amp;gt; [ 'disk' =&amp;gt; 'admin', 'directory' =&amp;gt; [ 'image' =&amp;gt; 'images', 'file' =&amp;gt; 'files', ] ], </code></pre> <p>将<code>disk</code>设置为上面添加的<code>admin</code>,<code>directory.image</code>和<code>directory.file</code>分别为用<code>$form-&amp;gt;image($column)</code>和<code>$form-&amp;gt;file($column)</code>上传的图片和文件的上传目录。</p> <p>当然你也可以在代码中指定<code>disk</code>:</p> <pre><code class="language-php">$form-&amp;gt;file('file')-&amp;gt;disk('your disk name');</code></pre> <p>&lt;a name=&quot;oss&quot;&gt;&lt;/a&gt;</p> <h2>云盘上传</h2> <p>如果需要上传到云存储,需要安装对应<code>laravel storage</code>的适配器,拿七牛云存储举例</p> <p>首先安装 <a href="https://github.com/zgldh/qiniu-laravel-storage">zgldh/qiniu-laravel-storage</a></p> <p>同样配置好disk,在<code>config/filesystems.php</code> 添加一项:</p> <pre><code class="language-php">'disks' =&amp;gt; [ ... , 'qiniu' =&amp;gt; [ 'driver' =&amp;gt; 'qiniu', 'domains' =&amp;gt; [ 'default' =&amp;gt; 'xxxxx.com1.z0.glb.clouddn.com', //你的七牛域名 'https' =&amp;gt; 'dn-yourdomain.qbox.me', //你的HTTPS域名 'custom' =&amp;gt; 'static.abc.com', //你的自定义域名 ], 'access_key'=&amp;gt; '', //AccessKey 'secret_key'=&amp;gt; '', //SecretKey 'bucket' =&amp;gt; '', //Bucket名字 'notify_url'=&amp;gt; '', //持久化处理回调地址 'url' =&amp;gt; 'http://of8kfibjo.bkt.clouddn.com/', // 填写文件访问根url ], ], </code></pre> <p>然后修改<code>dcat-admin</code>的上传配置,打开<code>config/admin.php</code>找到:</p> <pre><code class="language-php"> 'upload' =&amp;gt; [ 'disk' =&amp;gt; 'qiniu', 'directory' =&amp;gt; [ 'image' =&amp;gt; 'image', 'file' =&amp;gt; 'file', ], ], </code></pre> <p><code>disk</code>选择上面配置的<code>qiniu</code>,或:</p> <pre><code class="language-php">$form-&amp;gt;file('file')-&amp;gt;disk('qiniu');</code></pre> <p>&lt;a name=&quot;public&quot;&gt;&lt;/a&gt;</p> <h2>公共方法</h2> <h3>缩略图 (thumbnail)</h3> <p>上传图片的同时生成缩略图</p> <pre><code class="language-php">$form-&amp;gt;image($column[, $label])-&amp;gt;thumbnail('small', $width = 300, $height = 300); // 生成多张缩略图 $form-&amp;gt;image($column[, $label])-&amp;gt;thumbnail([ 'small1' =&amp;gt; [100, 100], 'small2' =&amp;gt; [200, 200], 'small3' =&amp;gt; [300, 300], ]);</code></pre> <pre><code class="language-php">use Dcat\Admin\Traits\Resizable; class Photo extends Model { use Resizable; } // To access thumbnail $photo-&amp;gt;thumbnail('small', 'photo_column');</code></pre> <p>&lt;a name=&quot;disk&quot;&gt;&lt;/a&gt;</p> <h3>存储驱动 (disk)</h3> <p>修改文件上传源</p> <pre><code class="language-php">$form-&amp;gt;file('file')-&amp;gt;disk('your disk name');</code></pre> <p>&lt;a name=&quot;move&quot;&gt;&lt;/a&gt;</p> <h3>上传路径 (move)</h3> <p>修改上传路径</p> <pre><code class="language-php">$form-&amp;gt;file('file')-&amp;gt;move('public/upload/image1/');</code></pre> <p>&lt;a name=&quot;name&quot;&gt;&lt;/a&gt;</p> <h3>文件名称 (name)</h3> <p>修改上传文件名称</p> <pre><code class="language-php">$form-&amp;gt;file('file')-&amp;gt;name('test.text'); $form-&amp;gt;image('picture')-&amp;gt;name(function ($file) { return 'test.'.$file-&amp;gt;guessExtension(); });</code></pre> <p>&lt;a name=&quot;uniqueName&quot;&gt;&lt;/a&gt;</p> <h3>随机名称 (uniqueName)</h3> <p>使用随机生成文件名 (md5(uniqid()).extension)</p> <pre><code class="language-php">$form-&amp;gt;image('picture')-&amp;gt;uniqueName();</code></pre> <p>&lt;a name=&quot;removable&quot;&gt;&lt;/a&gt;</p> <h3>禁止页面删除文件 (替换上传)</h3> <p>通过<code>removable</code>方法可以禁止用户从页面点击删除服务器上的文件,可以实现图片覆盖上传效果。</p> <pre><code class="language-php">$form-&amp;gt;file($column[, $label])-&amp;gt;removable(false);</code></pre> <p>&lt;a name=&quot;autoUpload&quot;&gt;&lt;/a&gt;</p> <h3>自动上传 (autoUpload)</h3> <p>开启这个功能之后选择完文件之后会立即自动上传,页面将不再显示<code>上传</code>按钮,使用方法如下</p> <pre><code class="language-php">$form-&amp;gt;file('file')-&amp;gt;autoUpload(); $form-&amp;gt;image('img')-&amp;gt;autoUpload();</code></pre> <p>&lt;a name=&quot;retainable&quot;&gt;&lt;/a&gt;</p> <h3>禁止删除 (retainable)</h3> <p>开启这个功能之后文件将不会从服务器删除</p> <pre><code class="language-php">$form-&amp;gt;file('file')-&amp;gt;retainable(); $form-&amp;gt;image('img')-&amp;gt;retainable();</code></pre> <p>&lt;a name=&quot;storagePermission&quot;&gt;&lt;/a&gt;</p> <h3>storagePermission</h3> <p>设置上传文件的权限</p> <pre><code class="language-php">$form-&amp;gt;image('picture')-&amp;gt;storagePermission(777);</code></pre> <p>&lt;a name=&quot;accept&quot;&gt;&lt;/a&gt;</p> <h3>限制上传文件类型</h3> <p>限制上传文件的类型</p> <pre><code class="language-php">$form-&amp;gt;file('file')-&amp;gt;accept('jpg,png,gif,jpeg'); // 可以指定 mimeTypes, 多个用逗号分割 $form-&amp;gt;file('file')-&amp;gt;accept('jpg,png,gif,jpeg', 'image/*');</code></pre> <p>&lt;a name=&quot;chunked&quot;&gt;&lt;/a&gt;</p> <h3>分块上传 (chunked)</h3> <p>启用分块上传</p> <pre><code class="language-php">$form-&amp;gt;file('file')-&amp;gt;chunked();</code></pre> <p>&lt;a name=&quot;chunkSize&quot;&gt;&lt;/a&gt;</p> <h3>分块大小(chunkSize)</h3> <p>设置分块大小,单位为<code>KB</code>,默认<code>5MB</code></p> <p>&gt; {tip} 调用这个方法会自动启用分块上传</p> <pre><code class="language-php">// 设置为 1MB $form-&amp;gt;file('file')-&amp;gt;chunkSize(1024);</code></pre> <p>&lt;a name=&quot;maxSize&quot;&gt;&lt;/a&gt;</p> <h3>文件大小(maxSize)</h3> <p>设置单个文件最大大小,单位为<code>Kb</code>,默认大小为<code>10M</code>。</p> <p>&gt; {tip} 同时应该保证<code>php.ini</code>配置文件的<code>upload_max_filesize</code>参数值必须大于这个方法设置的值。</p> <pre><code class="language-php">// 设置单个文件最大为1Mb $form-&amp;gt;file('file')-&amp;gt;maxSize(1024);</code></pre> <p>&lt;a name=&quot;threads&quot;&gt;&lt;/a&gt;</p> <h3>并发上传线程数 (threads)</h3> <p>设置并发上传线程数,默认<code>3</code></p> <pre><code class="language-php">$form-&amp;gt;file('file')-&amp;gt;threads(5);</code></pre> <p>&lt;a name=&quot;url&quot;&gt;&lt;/a&gt;</p> <h3>自定义上传接口 (url)</h3> <p>通过<code>url</code>可以设置自定义上传接口</p> <pre><code class="language-php">$form-&amp;gt;file('file')-&amp;gt;url('users/files');</code></pre> <p>系统提供了<code>Dcat\Admin\Traits\HasUploadedFile</code>这个<code>trait</code>来帮助开发者更轻松地处理上传文件,用法如下</p> <pre><code class="language-php">&amp;lt;?php namespace App\Admin\Controllers; use Dcat\Admin\Traits\HasUploadedFile; class FileController { use HasUploadedFile; public function handle() { $disk = $this-&amp;gt;disk('local'); // 判断是否是删除文件请求 if ($this-&amp;gt;isDeleteRequest()) { // 删除文件并响应 return $this-&amp;gt;deleteFileAndResponse($disk); } // 获取上传的文件 $file = $this-&amp;gt;file(); // 获取上传的字段名称 $column = $this-&amp;gt;uploader()-&amp;gt;upload_column; $dir = 'my-images'; $newName = $column.'-我的文件名称.'.$file-&amp;gt;getClientOriginalExtension(); $result = $disk-&amp;gt;putFileAs($dir, $file, $newName); $path = &amp;quot;{$dir}/$newName&amp;quot;; return $result ? $this-&amp;gt;responseUploaded($path, $disk-&amp;gt;url($path)) : $this-&amp;gt;responseErrorMessage('文件上传失败'); } }</code></pre> <p>在你的路由文件<code>app\Admin\routes.php</code>中加上</p> <pre><code class="language-php">$router-&amp;gt;any('users/files', 'FileController@handle');</code></pre> <p>&lt;a name=&quot;deleteUrl&quot;&gt;&lt;/a&gt;</p> <h3>deleteUrl</h3> <p>修改删除已上传文件路径,此方法一般不需要修改</p> <pre><code class="language-php">$form-&amp;gt;file('file')-&amp;gt;deleteUrl('file/delete');</code></pre> <p>&lt;a name=&quot;autoSave&quot;&gt;&lt;/a&gt;</p> <h3>自动保存字段值 (autoSave)</h3> <p>设置上传文件后是否自动保存文件路径到数据库,此方法默认启用,一般不需要修改</p> <pre><code class="language-php">$form-&amp;gt;file('file')-&amp;gt;autoSave(false);</code></pre> <p>&lt;a name=&quot;options&quot;&gt;&lt;/a&gt;</p> <h3>配置 (options)</h3> <p>自定义<a href="https://fex.baidu.com/webuploader/document.html">webuploader</a>配置</p> <pre><code class="language-php">$form-&amp;gt;file('file')-&amp;gt;options(['disableGlobalDnd' =&amp;gt; true]);</code></pre> <h3>可排序 (sortable)</h3> <p>此方法仅针对多图/文件上传表单有效</p> <pre><code class="language-php">$form-&amp;gt;multipleImage('images')-&amp;gt;sortable();</code></pre> <h3>压缩图片 (compress)</h3> <p>默认不启用</p> <pre><code class="language-php">// 启用图片压缩功能 $form-&amp;gt;multipleImage('images')-&amp;gt;compress(); $form-&amp;gt;image('avatar')-&amp;gt;compress([ 'width' =&amp;gt; 1600, 'height' =&amp;gt; 1600, // 图片质量,只有type为`image/jpeg`的时候才有效。 'quality' =&amp;gt; 90, // 是否允许放大,如果想要生成小图的时候不失真,此选项应该设置为false. 'allowMagnify' =&amp;gt; false, // 是否允许裁剪。 'crop' =&amp;gt; false, // 是否保留头部meta信息。 'preserveHeaders' =&amp;gt; true, // 如果发现压缩后文件大小比原来还大,则使用原来图片 // 此属性可能会影响图片自动纠正功能 'noCompressIfLarger' =&amp;gt; false, // 单位字节,如果图片大小小于此值,不会采用压缩。 'compressSize' =&amp;gt; 0 ]);</code></pre> <h3>监听WebUploader文件上传事件 (on)</h3> <p>通过 <code>on</code> 方法可以监听 <a href="http://fex.baidu.com/webuploader/doc/index.html#WebUploader_Uploader_events">WebUploader文件上传相关事件</a></p> <pre><code class="language-php">$form-&amp;gt;file('...') -&amp;gt;on('startUpload', &amp;lt;&amp;lt;&amp;lt;JS function () { console.log('文件开始上传...', this); // 上传文件前附加自定义参数到文件上传接口 this.uploader.options.formData['custom_field'] = '...'; } &amp;lt;&amp;lt;&amp;lt;JS ) -&amp;gt;on('uploadFinished', &amp;lt;&amp;lt;&amp;lt;JS function () { console.log('文件上传完毕'); } &amp;lt;&amp;lt;&amp;lt;JS );</code></pre> <p>&lt;a name=&quot;withhost&quot;&gt;&lt;/a&gt;</p> <h3>文件/图片域名拼接</h3> <p>文件或图片上传表单字段请不要在模型中设置<strong>访问器</strong>和<strong>修改器</strong>拼接域名,如果你需要在访问的时候拼接完整域名,可以在模型中定义一个<code>public</code>方法</p> <pre><code class="language-php">&amp;lt;?php use Illuminate\Support\Str; use Illuminate\Support\Facades\Storage; class YourModel extends Model { // 定义一个public方法访问图片或文件 public function getImage() { if (Str::contains($this-&amp;gt;image, '//')) { return $this-&amp;gt;image; } return Storage::disk('admin')-&amp;gt;url($this-&amp;gt;image); } }</code></pre> <h3>保存域名</h3> <p>如果你需要保存文件域名到数据表,可以使用<code>saveFullUrl</code>方法</p> <pre><code class="language-php">$form-&amp;gt;image('avatar')-&amp;gt;saveFullUrl(); $form-&amp;gt;file('...')-&amp;gt;saveFullUrl();</code></pre> <h3>监听文件上传变动 (change)</h3> <p>通过以下方法可以监听文件<strong>上传成功</strong>或文件<strong>被删除</strong>时产生的变动</p> <pre><code class="language-php">$file = $form-&amp;gt;file('...'); Admin::script( &amp;lt;&amp;lt;&amp;lt;JS $('{$file-&amp;gt;getElementClassSelector()} .file-input').on('change', function () { console.log('文件发生变动', this.value); }); JS );</code></pre> <p>&lt;a name=&quot;override&quot;&gt;&lt;/a&gt;</p> <h3>覆盖上传 (override)</h3> <p>通过 <code>override</code> 方法可以实现文件覆盖上传。</p> <pre><code class="language-php">$form-&amp;gt;file('file')-&amp;gt;override(); $form-&amp;gt;image('img')-&amp;gt;override();</code></pre> <p>&lt;a name=&quot;imagefun&quot;&gt;&lt;/a&gt;</p> <h2>图片上传内置方法</h2> <p>&lt;a name=&quot;intervention&quot;&gt;&lt;/a&gt;</p> <h3>压缩、裁切、添加水印等</h3> <p>可以使用压缩、裁切、添加水印等各种方法,需要先安装<a href="http://image.intervention.io/getting_started/installation">intervention/image</a>.</p> <p>更多使用方法请参考[<a href="http://image.intervention.io/getting_started/introduction">Intervention</a>]:</p> <pre><code class="language-php">$form-&amp;gt;image($column[, $label]); // 修改图片上传路径和文件名 $form-&amp;gt;image($column[, $label])-&amp;gt;move($dir, $name); // 剪裁图片 $form-&amp;gt;image($column[, $label])-&amp;gt;crop(int $width, int $height, [int $x, int $y]); // 加水印 $form-&amp;gt;image($column[, $label])-&amp;gt;insert($watermark, 'center');</code></pre> <p>&lt;a name=&quot;dimensions&quot;&gt;&lt;/a&gt;</p> <h3>限制上传图片的尺寸</h3> <p>设置文件上传尺寸限制</p> <p>参数: <code>array</code> 单位为像素</p> <ul> <li><code>width</code> 指定宽度</li> <li><code>height</code> 指定高度</li> <li><code>min_width</code> 最小宽度</li> <li><code>min_height</code> 最小高度</li> <li><code>max_width</code> 最大宽度</li> <li><code>max_height</code> 最大高度</li> <li><code>ratio</code> 宽高比 (width/height)</li> </ul> <pre><code class="language-php">// 上传宽度为100-300像素之间的图片 $form-&amp;gt;image('img')-&amp;gt;dimensions(['min_width' = 100, 'max_width' =&amp;gt; 300]);</code></pre> <p>&lt;a name=&quot;referer&quot;&gt;&lt;/a&gt;</p> <h2>把图片/文件路径保存在其他数据表</h2> <p>通过下面的方法可以把图片或文件的路径保存在单独的附件表,而当前的图片/文件字段只保存ID</p> <p>&gt; {tip} 这里的示例用的是单图上传表单,如果是多图的话可以按这个思路自行调整。</p> <p>图片/文件表结构</p> <pre><code class="language-sql">CREATE TABLE `images` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `path` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '', `created_at` timestamp NULL DEFAULT NULL, `updated_at` timestamp NULL DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;</code></pre> <p>使用</p> <pre><code class="language-php">$form-&amp;gt;image('image1') -&amp;gt;saving(function ($value) use ($form) { if ($form-&amp;gt;isEditing() &amp;amp;&amp;amp; ! $value) { // 编辑页面,删除图片逻辑 Image::destroy($form-&amp;gt;model()-&amp;gt;image1); return; } // 新增或编辑页面上传图片 if ($value) { $model = Image::where('path', $value)-&amp;gt;first(); } if (empty($model)) { $model = new Image(); } $model-&amp;gt;path = $value; $model-&amp;gt;save(); return $model-&amp;gt;getKey(); }) -&amp;gt;customFormat(function ($v) { if (! $v) { return; } return Image::find((array) $v)-&amp;gt;pluck('path')-&amp;gt;toArray(); });</code></pre> <h2>文件上传失败或无法访问?</h2> <p>如果你发现无法上传文件,那么通常有几下几点原因:</p> <ol> <li><code>Laravel</code>文件上传配置不正确,请检查<code>admin.upload.disk</code>参数。如果你不了解<code>laravel</code>文件上传功能,请阅读文档<a href="https://learnku.com/docs/laravel/7.x/filesystem/7485">Laravel - 文件存储</a></li> <li>文件过大,需要调整<code>php.ini</code>的<code>upload_max_filesize</code>参数</li> <li>文件上传目录没有写权限</li> <li><code>php</code>没有安装或没有开启<code>fileinfo</code>扩展</li> </ol> <p>如果你的文件上传成功了,却无法正常访问,那么可能是<code>.env</code>配置文件中的<code>APP_URL</code>参数没有设置正确。</p>

页面列表

ITEM_HTML