【问题标题】:Custom chunk implementation自定义块实现
【发布时间】:2020-03-31 20:28:26
【问题描述】:

是否可以在Filepond中自定义chunk配置,以便将chunk信息提供给上传服务器:

  • 作为查询参数而不是标题
  • 使用自定义查询参数名称而不是 Upload-LengthUpload-NameUpload-Offset

我正在尝试将 Filepond 的块实现适配到我无法控制的第三方上传端点。

我找到了Advanced configuration,您在其中提供了一个过程功能,我已经玩了一点,看看选项参数会带来什么——但这似乎(我认为)让分块计算成为我的责任。我最初的想法是操纵options.chunkServer.url 以包含我需要的查询参数,但我不相信这会处理单个块。

如果它有所作为,这是在 React 中使用 react-filepond package 完成的。

【问题讨论】:

  • 我认为您将不得不使用自定义处理方法,目前无法解决。我建议使用您可以在存储库中找到的 FilePond 代码并将其中的一些复制粘贴到您的方法中。

标签: filepond


【解决方案1】:

我在 Laravel 6 中使用 Traits 和一些“不好的做法”(我没有时间,因为......在 prod 中发布)将块加入文件中并实现了

基本上:

  1. 发布以获取唯一 ID 文件夹进行存储
  2. 获取块并连接在一起
  3. 利润!

这是完整的代码:

<?php

namespace App\Http\Traits\Upload;

use Closure;
use Faker\Factory as Faker;
use Illuminate\Http\Request;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;

trait Uploadeable
{
   public function uploadFileInStorage(Request $request, Closure $closure)
   {
       // get the nex offset for next chunk send
       if (($request->isMethod('options') || $request->isMethod('head')) && $request->has('patch')) {

           //get the temp dir
           $dir = $request->patch . DIRECTORY_SEPARATOR;

           // reead all chunks in directory
           $patch = collect(Storage::files($dir))
               ->sortBy(function ($file) {
                   return Storage::lastModified($file);
               });

           // read offsets for calculate
           $offsets = array();
           $size = 0;
           $last_offset = 0;
           foreach ($patch as $filename) {
               $size = Storage::size($filename);

               list($dir, $offset) = explode('file.patch.', $filename, 2);

               array_push($offsets, $offset);

               if ($offset > 0 && !in_array($offset - $size, $offsets)) {
                   $last_offset = $offset - $size;
                   break;
               }

               // last offset is at least next offset
               $last_offset = $offset + $size;
           }
           // return offset
           return response($last_offset, 200)
               ->header('Upload-Offset', $last_offset);
       }

       // chunks
       if ($request->isMethod('patch') && $request->has('patch')) {
           // get the temp dir
           $dir = $request->patch . DIRECTORY_SEPARATOR;

           // read headers
           $offset = $request->header('upload-offset');
           $length = $request->header('upload-length');

           // should be numeric values, else exit
           if (!is_numeric($offset) || !is_numeric($length)) {
               return response('', 400);
           }

           // get the file name
           $name = $request->header('Upload-Name');

           // sleep server for get a diference between file created to sort
           usleep(500000);

           // storage the chunk with name + offset
           Storage::put($dir . 'file.patch.' . $offset, $request->getContent());

           // calculate total size of patches
           $size = 0;
           $patch = Storage::files($dir);
           foreach ($patch as $filename) {
               $size += Storage::size($filename);
           }

           // make the final file
           if ($size == $length) {
               // read all chunks in directory
               $files = collect(Storage::files($dir))
                   ->sortBy(function ($file) {
                       return Storage::lastModified($file);
                   });

               // create output file
               //Log::info(storage_path('app'));
               $new_file_name = $final_name = trim(storage_path('app') . DIRECTORY_SEPARATOR . $dir . $name);
               $file_handle = fopen($new_file_name, 'w');

               // write patches to file
               foreach ($files as $filename) {
                   // get offset from filename
                   list($dir, $offset) = explode('.patch.', $filename, 2);

                   // read chunk
                   $patch_handle = fopen(storage_path('app') . DIRECTORY_SEPARATOR . trim($filename), 'r');
                   $patch_contents = fread($patch_handle, filesize(storage_path('app') . DIRECTORY_SEPARATOR . trim($filename)));
                   fclose($patch_handle);

                   // apply patch
                   fseek($file_handle, $offset);
                   fwrite($file_handle, $patch_contents);
               }

               // done with file
               fclose($file_handle);

               // file permission (prefered 0755)
               chmod($final_name, 0777);

               // remove patches
               foreach ($patch as $filename) {
                   $new_file_name = storage_path('app') . DIRECTORY_SEPARATOR . trim($filename);
                   unlink($new_file_name);
               }
               
               // simple class (no time to explain)
               $file = new UploadedFile(
                   $final_name,
                   basename($final_name),
                   mime_content_type($final_name),
                   filesize($final_name),
                   false
               );

               $dir = $request->patch . DIRECTORY_SEPARATOR;

               $object = new \stdClass();
               $object->full_path = (string)$file->getPathname();
               $object->directory = (string)($dir);
               $object->path = (string)($dir . basename($final_name));
               $object->name = (string)$file->getClientOriginalName();
               $object->mime_type = (string)$file->getClientMimeType();
               $object->extension = (string)$file->getExtension();
               $object->size = (string)$this->formatSizeUnits($file->getSize());

               // exec closure
               $closure($file, (object)$object, $request);
           }

           // response
           return response()->json([
               'message' => 'Archivo subido correctamente.',
               'filename' => $name
           ], 200);
       }

       // get dir unique id folder temp
       if ($request->isMethod('post')) {
           $faker = Faker::create();
           $unique_id = $faker->uuid . '-' . time();
           $unique_folder_path = $unique_id;

           // create directory
           Storage::makeDirectory($unique_folder_path);

           // permisos directorio
           chmod(storage_path('app') . DIRECTORY_SEPARATOR . $unique_folder_path . DIRECTORY_SEPARATOR, 0777);

           // response with folder
           return response($unique_id, 200)
               ->header('Content-Type', 'text/plain');
       }
   }

   private function formatSizeUnits($bytes)
   {
       if ($bytes >= 1073741824) {
           $bytes = number_format($bytes / 1073741824, 2) . ' GB';
       } elseif ($bytes >= 1048576) {
           $bytes = number_format($bytes / 1048576, 2) . ' MB';
       } elseif ($bytes >= 1024) {
           $bytes = number_format($bytes / 1024, 2) . ' KB';
       } elseif ($bytes > 1) {
           $bytes = $bytes . ' bytes';
       } elseif ($bytes == 1) {
           $bytes = $bytes . ' byte';
       } else {
           $bytes = '0 bytes';
       }

       return $bytes;
   }
}
´´´

【讨论】:

    猜你喜欢
    • 2012-07-27
    • 1970-01-01
    • 2013-08-10
    • 2012-02-11
    • 2014-02-01
    • 2014-10-14
    • 2011-06-04
    • 2010-10-29
    • 2011-01-10
    相关资源
    最近更新 更多