clevis/files-upload-control

Nette Forms 的文件上传控制。

dev-master 2015-03-30 14:51 UTC

This package is not auto-updated.

Last update: 2024-09-23 15:27:33 UTC


README

表单组件用于文件上传。请下载并创建一个模板,默认模板可能不适合您。

允许以两种方式发送文件

  • 正常表单方式。
  • Ajax方式。

在处理表单时,您将获得作为字段元素的实体值,这些实体代表文件。请参阅与模型的连接。

Ajax信号的API是根据jQuery File Upload Plugin定制的,但应与其他上传库兼容。请参阅与前端连接。

兼容性

测试通过Nette @dev (目前为 nette/nette@ae11ca1) 和 2.0.12

在PHP 5.3上测试不会通过 - 我在闭包中多次使用了 $this,并且可能还有一些缩写的数组... 但是组件应该在PHP 5.3上工作。

与模板工厂的连接

组件要求在服务容器中有一个名为 "templateFactory" 的服务,它有一个公共方法 createTemplate($file, Nette\Application\UI\Control $control)

这有点复杂,但在这里不会详细说明正确的解决方案(正确的解决方案应该有一个接口,该接口在另一个包中定义,该包要求这个包;最好的情况是,这个接口已经在Nette中定义了)。

与模型的连接

这个组件的构造函数传递一个 IFilesRepository 对象,该对象负责 CRUD IFileEntity 类型实体。它可以部署在 PetrP/OrmTharos/LeanMapper 上。仓库还负责将文件移动到临时目录之外。

请注意,仅在通过信号上传时调用 saveFile。对于通过表单上传的文件,您必须在表单处理程序中处理实体的存储。

与前端连接

Nette中每个表单元素的属性是 htmlName,POST变量的名称由此派生。

  • htmlName[] - 上传的文件。
  • htmlName-autoUploaded[] - 通过Ajax上传的文件的ID。仅在此处处理表单发送。

因此,通过HTML上传由 <input type="file" name="{$control->htmlName}[]"> 处理,任何Ajax上传器也使用相同的名称(只是不同的URL,下面会详细说明)。

Ajax上传器在Ajax上传成功后应将 <input type="hidden" name="{$control->htmlName}-autoUploaded[]" value="..."> 插入到表单中,其中 value 将是上传文件的ID(从上传信号的payload中获取)。这样表单就会记住通过它上传了哪些文件,并在提交后从仓库中提取它们的实体。

这个组件不仅限于上传新文件,还可以成功用于更改现有文件的顺序。只需列出它们,并为每个添加一个 hiddenhtmlName-autoUploaded[]。添加jQuery sortable,任务完成。在处理时,您将获得所有文件的正确顺序数组。

Ajax上传信号

{$control->getUploadLink()}

接受 htmlName[] 中的文件,返回以下格式的JSON payload

{
	"files": [
		{
			"id": 1,
			"name": "nazev-souboru.txt",
			"size": 123,
			"type": "text/plain",
			"delete_type": "DELETE",
			"delete_url": "URL delete signálu",
			"thumbnail_url": "URL náhledu",
			"url": "URL plné velikosti"
		},
		{
			"id": 1,
			"name": "jini-soubor.gif",
			"size": 666,
			"type": "image/gif",
			"delete_type": "DELETE",
			"delete_url": "URL delete signálu",
			"thumbnail_url": "...",
			"url": "..."
		},
		{
			"name": "prilis-velky-soubor.txt",
			"error": "Maximální povolená velikost souboru je 123."
		},
		{
			"name": "vice-problemu.gif",
			"error": [
				"Je vyžadována přípona TXT.",
				"Maximální povolená velikost souboru je 123."
			]
		}
	]
}

仅在组件定义了 IUrlProvider 时,thumbnail_urlurl 的值才在响应中。如果格式不符合要求,您可以重定义 createFilePayload()createErrorPayload() 方法。

仅根据以下规则进行上传验证

  • FilesUploadControl::MAX_FILE_SIZE
  • FilesUploadControl::MIME_TYPE
  • FilesUploadControl::IMAGE
  • FilesUploadControl::RULE_EXTENSION

如果控件上部署了其他验证器,那么这些验证器将在表单提交后才会被调用。

Ajax 删除信号

{$control->getDeleteLink(IFileEntity $file)}

如果组件设置了会话部分(参见 setAutoUploadsSessionSection()),则可以通过此信号删除(或调用 IFilesRepositor::deleteFile())通过上传信号上传的文件,但这些文件在表单提交时还没有被处理。

即使没有设置会话,或者会话中不存在该文件,也会调用 onBeforeDeleteonDelete 事件,因此您可以扩展此行为。

无论操作结果如何,都会返回此响应

{
	"success": true
}

组件设置

可选依赖

  • setUrlProvider(IFileUrlProvider $urlProvider) - 如果上传信号需要返回 URL 和预览 URL,则需要知道如何操作。
  • setAutoUploadsSessionSection(SessionSection $autoUploadsSession) - 如果要使用删除信号。

事件

  • onAutoUpload(IFileEntity $file, \ArrayObject $filePayload) - 在文件上传信号保存文件后。可以修改 payload(这是一个 ArrayObject,因为我在传递数组引用时遇到了一些问题,现在不知道是什么问题)。
  • onBeforeDelete(IFileEntity $file) - 在删除前。
  • onDelete(IFileEntity $file) - 删除后,即使没有成功,也会调用。这可能需要更改。

防止 CSRF 攻击

如果表单通过 Form::addProtection() 受保护,则此组件的 Ajax 信号也将受保护。方法 getUploadLink()getDeleteLink() 会将令牌添加到信号 URL,并在处理信号时进行检查。