tacoberu/nette-form-fileupload 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

tacoberu/nette-form-fileupload

Composer 安装命令:

composer require tacoberu/nette-form-fileupload

包简介

Uploading files has its specifics. It is not enough just to upload the file. We also want to show it when it's already uploaded (preferably with a preview). We want to possibly delete it or replace it with another version.

README 文档

README

FileControl and MultiFileControl are Nette form inputs for file uploading that behave exactly like other Nette inputs: setValue() sets the value, getValue() returns it, and validation, conditional validation, and error messages work identically to text or select inputs.

The standard <input type="file"> has several inconveniences when editing existing data:

  1. The original file cannot be shown in any reasonable way — unlike other inputs, where the original value can be displayed.
  2. Related to that is how to delete an existing file.
  3. When an unrelated error occurs elsewhere in the form, the user has to upload the file again.
  4. Uploading large files is a chapter of its own.

FileControl solves this:

  1. An existing file is represented by a value of the FileCurrent class. If the user deletes it, the form knows about it.
  2. Uploaded files are kept in a transaction — once uploaded, a file does not need to be uploaded again even if the form fails for another reason.

The input value can take one of three forms:

  • null — no file, or the original file was deleted
  • FileUploaded — a newly uploaded file (stored in the transaction, waiting to be committed to the system)
  • FileCurrent — the original file stored in the system

Version and requirements

Branch PHP Nette
v2.0 >= 8.1 ^3.2
v1.2 >= 7.4 ^3.1

Quick start

Register the extension in config.neon:

extensions:
    filecontrol: Taco\Nette\Forms\Controls\FileControlExtension

filecontrol:
    store: Taco\Nette\Forms\Controls\UploadStoreTemp('uploading/txt-', null, %tempDir%)

Use in a form:

$form->addFileControl('portrait', 'Portrait');
$form->addMultiFileControl('attachments', 'Attachments');

A form with a single file (FileControl) — an uploaded file has a delete button:

Form with FileControl

A form with multiple files (MultiFileControl) — with image previews, deletion of individual items (✕) and the ↻ button for preloading:

Form with MultiFileControl

Typical form with an avatar

Runnable examples are available in the examples/ directory.

Features

No-JS mode

The controls are fully functional without JavaScript. The ↻ button lets the user upload files before submitting the form — the page does a full round-trip, but all form state is preserved. Validation, errors, and the transaction mechanism all work the same way.

JS enhancements: AJAX upload and ↻ button helpers

The controls are fully functional without any JS (see above) — the ↻ button is visible and the user clicks it manually. On top of that baseline, assets/filecontrol.ts / assets/filecontrol.js offer optional JS enhancements that can be integrated into any frontend:

  • initMultiFileAjaxUpload(container) — replaces the round-trip with an immediate AJAX upload for MultiFileControl. Activates based on the container's data-upload-url attribute — the library sets that itself whenever the control is rendered within a Presenter, so it's nothing you need to manage.
  • initFileAjaxUpload(container) — the same for FileControl.
  • initMultiFileAutoPreload(container) — for when no AJAX URL is available: hides the ↻ button and clicks it automatically once files are selected, so the round-trip happens on its own instead of requiring a manual click.
  • initFileHideOnNew(container) — the equivalent for FileControl: hides the delete button and the original file's label once a new file is selected, so they don't get in the way.
  • initFileClearButton(fileInput) — inserts a ✕ button after <input type="file"> to clear the selected files.

AJAX upload features (initMultiFileAjaxUpload / initFileAjaxUpload):

  • Immediate upload on file selection — no need to click ↻ or submit the form
  • Chunked transfer for large files — files are automatically split so each POST stays within upload_max_filesize; the server reassembles them inside the transaction
  • Progress bar — a <progress> element is shown during chunked transfers
  • Inline preview — the server returns a thumbnail or filename label, inserted into the page without a full reload
import {
    initMultiFileAjaxUpload, initMultiFileAutoPreload,
    initFileAjaxUpload, initFileHideOnNew, initFileClearButton,
} from './filecontrol.js';

// data-upload-url is set by the library itself whenever the control is rendered
// within a Presenter — here it's only used to decide whether to wire up AJAX
// or the JS helper for the manual ↻ button.
document.querySelectorAll('[data-taco-type="file multiple"]').forEach(el => {
    el.dataset.uploadUrl ? initMultiFileAjaxUpload(el) : initMultiFileAutoPreload(el);
});
document.querySelectorAll('.taco-filecontrol-single').forEach(el => {
    el.dataset.uploadUrl ? initFileAjaxUpload(el) : initFileHideOnNew(el);
});
document.querySelectorAll('.taco-filecontrol-single input[type="file"]')
    .forEach(initFileClearButton);

Validation

Works exactly like other Nette inputs — fully compatible with addConditionOn(), addRule(), and error messages:

$form->addFileControl('portrait', 'Portrait')
    ->setRequired('Please select a file.')
    ->addRule($form::MaxFileSize, 'File is too large (max %d B).', 512 * 1024)
    ->addRule($form::MimeType, 'Only images are allowed.', ['image/jpeg', 'image/png'])
    ->addRule($form::Image, 'File must be an image.');
Rule Description
Form::Required / setRequired() A file must be selected or already exist as FileCurrent.
Form::MaxFileSize Maximum file size in bytes.
Form::MimeType Allowed MIME types, e.g. 'image/jpeg' or an array of types.
Form::Image Shorthand for supported image formats (image/jpeg, image/png, image/gif, image/webp).

Upload errors

  • A file exceeds upload_max_filesize — PHP marks the file with UPLOAD_ERR_INI_SIZE; the control displays a message with the limit value.
  • The combined upload exceeds post_max_size — PHP silently discards the entire POST body. The control detects this from Content-Length and adds a form-level error.

API

setPreviewer()

Sets a previewer for formatting file previews. GenericFilePreviewer displays image thumbnails.

getRemoveButtonPrototype()

Allows customizing the delete button: label, classes, title.

Transactions

An uploaded file is automatically moved to the storage (transaction). This means the file does not need to be uploaded again on a validation error. After successful processing, it is available via getValue() like any other value.

Once committed to the system, the transaction can be discarded explicitly:

$form['portrait']->destroyStore();

Or it can be left to the GC, which deletes it automatically after UploadStoreTemp::$gcAgeLimit expires.

Building assets (TypeScript)

npm run build:assets

Compiled output: assets/filecontrol.js (symlinked into examples/document_root/js/).

E2E tests (Playwright)

npm install
npx playwright install chromium  # first time only

npm run test:e2e        # run the tests
npm run test:e2e:ui     # interactive UI

The URL of the tested application is configured in .env via APP_URL. Outputs are saved to temp/.

tacoberu/nette-form-fileupload 适用场景与选型建议

tacoberu/nette-form-fileupload 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 446 次下载、GitHub Stars 达 0, 最近一次更新时间为 2024 年 04 月 25 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「file」 「form」 「upload」 「nette」 「remote」 「fileupload」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 tacoberu/nette-form-fileupload 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 tacoberu/nette-form-fileupload 我们能提供哪些服务?
定制开发 / 二次开发

基于 tacoberu/nette-form-fileupload 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 446
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 24
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 1
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2024-04-25