如何将文件上传与尚未创建的表单提交相关联?

How can I associate file uploads with a form submission that has not yet been created?

我正在构建一个传统的 server-rendered HTML 应用程序(在 PHP 之上使用 Statamic),让用户可以创造想法。他们访问创建创意表单,填写一些问题,然后单击提交。一旦他们这样做了,表单就会向服务器发送一个 POST 请求,然后服务器会保存数据,为这个想法生成一个 ID(和 slug)。

我现在想让用户上传文件作为他们想法的一部分。 old-fashioned 方法当然是将文件输入添加到表单,然后立即提交所有内容(数据和文件)。服务器可以创建一个 ID,然后将文件与该 ID 相关联。

但是,这种方法有一些缺点,尤其是作为表单提交过程的一部分必须等待文件上传的延迟。更现代的实现似乎会在添加文件后立即上传文件(例如,通过 drag-and-drop)。我已经确定 FilePond as a front-runner, for instance, or else I would probably use Dropzone.js

但是,如果浏览器在用户提交表单之前发送文件,我怎样才能最好地将文件与表单数据相关联?我还没有可用的 ID。

这一定是一个已解决的问题。但是我无法通过 Google 找到任何最佳实践,因此出现了这个问题。我想到的可能解决方案:

  1. 生成 GUID 作为表单的一部分。与任何文件上传一起提交。如果最终提交表单,则将其保存(作为隐藏字段)作为表单数据的一部分。
  2. 要求用户在启用文件上传之前提交表单(保存草稿)。显然不是很好的用户体验。
  3. 作为上述 2) 的变体,在用户开始上传文件之前的某个时刻通过 Ajax 自动提交表单。

我倾向于解决方案 1,但想看看我可能没有想到什么。 2 不是很好,因为令人困惑的用户体验,而 3 似乎也不太理想,例如,因为我可能最终保存了用户从未实际保存(并放弃)的草稿想法,部分原因是生成的 slug 可能是基于缺失或不完整的标题,因为用户在上传文件之前可能没有填写标题字段。

这是我的建议:

  • 立即上传文件(验证后..)
  • 在数据库的 "files" table 中创建一个条目,其中第一个 path/filename(使其唯一!)和第二个唯一且足够长的令牌
  • 将其发送回您的表单(作为 return 从上传)和
  • 将其与隐藏输入中的表单一起提交。

然后创建一个 cronjob,大约每小时删除一次所有未使用的文件。

FilePond 的文档实际上有 description of a recommended setup:

Asynchronously uploading files with FilePond is called processing. In short, FilePond sends a file to the server and expects the server to return a unique file id. This unique id is then used to revert uploads or restore earlier uploads later on.

The upload process described over time:

  1. client uploads file my-file.jpg as multipart/form-data using a POST request
  2. server saves file to unique location tmp/12345/my-file.jpg
  3. server returns unique location id 12345 in text/plain response
  4. client stores unique id 12345 in a hidden input field
  5. client submits the FilePond parent form containing the hidden input field with the unique id
  6. server uses the unique id to move tmp/12345/my-file.jpg to its final location and remove the tmp/12345 folder