files-ui-react icon indicating copy to clipboard operation
files-ui-react copied to clipboard

FEATURE REQUEST: Allow client-side processing of files before uploading

Open OneHatRepo opened this issue 1 year ago • 4 comments

I'd like to be able to resize images on the client side before uploading them to the server. This would require some way to hook into the upload process.

I've tried Dropzone.onChange, but processing the images requires onChange to be an async handler, and it's currently not. i.e. If onChange returns a Promise, it would await that Promise before continuing on with the upload.

I've also tried the actionButtons / uploadButton with autoUpload = false. Using this prevents the automatic upload, and assigning an onClick handler to the uploadButton means I get to process the event, but I seem to have no way to initiate the upload once the processing is done. Is there a way to initiate the upload externally? That would solve the problem.

OneHatRepo avatar Jul 05 '24 15:07 OneHatRepo

Being able to do these requires you to edit the source code. for example I've implemented the custom upload button by passing a state to the dropzone component and using it inside a useEffect hook .

Pooyahmti avatar Jul 05 '24 19:07 Pooyahmti

@Pooyahmti I forked the repository and made a few tweaks to @files-ui/react/build/index.es.js, and that worked, but I'd rather have something actually built into the library. It seems like other people would like to be able to publicly access the uploadfiles() method of Dropzone.

OneHatRepo avatar Jul 05 '24 19:07 OneHatRepo

I have a similar scenario, which I could not solve due to the lack of support for async callbacks.

My upload endpoint requires to receive a pre-generated fileUuid for each file to upload, which I want to pass as path or query parameter. I cannot put it in FileExt.extraUploadData, because then the server needs to process the whole request body first before knowing the fileUuid, but it should be able to refuse performing the upload in advance, if the provided fileUuid is not valid.

This means, I need custom upload URLs for each single file. Generating a new fileUuid (and constructing the upload URL with it) is done through an asynchronous call to an external service.

This becomes a problem when the user uploads multiple files at once. I found out that it is possible to modify the upload URL for each file individually by setting the undocumented property ExtFile.uploadUrl, but if I do that within the onUploadStart() callback, the custom URL will only be used, if the callback executes synchronously - which does not allow me to request new fileUuids.

I also tried adding the custom URLs in the onChange() handler - but also here, as already stated, this handler fails if it contains asynchrounous calls. I tried circumventing them using ().then(() => {}) calls and to modify the URLs during the preperation period - but this seems to break the whole state handling and files ui does not render the proper preparing/uploading states anymore.

As a workaround, I now pre-generate new fileUuid's for the maximum possible number of uploadable files in advance on loading my component that I can use for upcoming uploads synchronously, which is not a very efficient way, but at least it works.

So - long story short - it would be really great to add the support of asynchronous callback functions - inclucing onChange, onUploadStart, onUploadFinish and onDelete...

Thanks in advance!

pjaydev avatar Jul 18 '25 11:07 pjaydev

Just now, I created a publicly accessible version of my fork here, so you all could see the changes I made.

In order to include this in a project, you just have to reference the exact commit with build files.

  "dependencies": {
    "@files-ui/react": "https://github.com/OneHat-Technologies/files-ui-react/archive/8222604.tar.gz"
  }

When you need to access to the uploadFiles method directly, you just import it:

import { DropzoneUploadFiles } from "@files-ui/react";

Then call it after your external processing is done:

DropzoneUploadFiles(files);

Make sure you set autoUpload to false on Dropzone.

<Dropzone
	value={files}
	onChange={onDropzoneChange}
	uploadConfig={{
		autoUpload: false,
	}}
></Dropzone>

OneHatRepo avatar Jul 18 '25 17:07 OneHatRepo