gRegor Posted March 4 Share Posted March 4 I've looked through quite a few threads and the source code, but unfortunately have not found exactly what I was looking for. I recently upgraded to PW 3.0.246 on PHP 8.2 and I'm wondering if there's some breaking changes I need to adjust for: I have an admin module using InputfieldFile (noAjax) that prompts for a CSV file and uses WireUpload to handle it by creating a unique name and moving the file to a longer-term location. This worked pretty smoothly on PW 3.0.165 (I think it was around that version), but seems to be failing now with "Unable to move uploaded file". Code snippets below. This is inside a Process module called ProcessMemberScorecard. These aren't large files and all the directories exist and should have correct permissions: // start out by creating a WireTempDir based on the class name $destination = $this->files->tempDir($this->className)->get(); // then an InputFieldWrapper is created and field configs with importArray() $wrapper->importArray( [ [ 'type' => 'file', 'name' => 'scores_upload', 'label' => 'Scores File', 'description' => 'Select a CSV file to upload', 'icon' => 'upload', 'extensions' => 'csv', 'destinationPath' => $destination, 'maxFiles' => 1, 'maxFilesize' => 10 * 1024 * 1024, 'noAjax' => true, 'descrptionRows' => 0, ], // more field configs... ] ); Then on POST request, the form is processed and a WireUpload is run: if ($this->input->requestMethod('POST')) { $form->processInput($this->input->post); $ul = new WireUpload('scores_upload'); $ul->setValidExtensions(['csv']); $ul->setMaxFiles(1); $ul->setOverwrite(true); // this appears to correctly set the full system path for /site/modules/ProcessMemberScorecard/.uploads/ and that folder exists and has a lot of previously uploaded files from this module $ul->setDestinationPath($this->config->paths($this) . '.uploads/'); // set up final filename for destination $dt = new DateTime(); $tmpname = bin2hex(random_bytes(8)); $ul->setTargetFilename( sprintf('%s-%s.csv', $dt->format('Y-m-d'), $tmpname ) ); $results = $ul->execute(); if (count($results) == 0) { foreach ($ul->getErrors() as $error) { $this->log->save('scorecard', $error); $this->error($error); } return $form->render(); } // get final filename from $results[0] and do additional processing } I'm still getting errors like "Unable to move uploaded file to: /site/modules/ProcessMemberScorecard/.uploads/2025-03-04-a4604381bbe12d34.csv" I have tried changing the permissions on that `.uploads` directory in the module to 0777 (bad!), but still getting the same error. Is there something in newer versions of WireUpload that prevent moving files into folders with a leading dot? I couldn't find anything like that in the source code, but just trying to think though all the possibilities. Thanks for any help! Link to comment Share on other sites More sharing options...
gRegor Posted March 5 Author Share Posted March 5 Hm, well a bit of progress: I realized that InputfieldFile has its own usage of WireUpload already (source). I was originally thinking that it uploaded the file only to a tmp directory, then I had to manually use WireUpload to move it to the long-term location. The InputfieldFile method will largely work, but unfortunately it doesn't let me call `setTargetFilename()` on the WireUpload, so I might not be able to enforce the naming scheme I was using. I'm still really curious why this stopped working after the upgrade. So far, comparing versions, InputfieldFile seems to work pretty similarly. Link to comment Share on other sites More sharing options...
gRegor Posted March 5 Author Share Posted March 5 I think I have this working, but part of it feels hacky. In the form config, I set the destinationPath to the final location (no intermediate temp directory): $destinationPath = $this->config->paths($this) . '.uploads/'; $destinationPath = $this->config->paths($this) . '.uploads/'; Calling processInput() will handle the upload and move the file to that destination using the original filename. That process also sets up a Pagefiles object as the value of the InputfieldFile. This is where it gets kinda hacky: That Pagefiles object defaults to the current admin page that the form is uploading via, so it sets the paths to that page ID instead of the destination path. Despite this, that is not where the uploaded file is. Example dump of the object (key parts): ProcessWire\InputfieldFile Object ( [className] => InputfieldFile [attributes] => Array ( ... [value] => ProcessWire\Pagefiles Object ( [count] => 1 [url] => /site/assets/files/####/ [path] => /full/path/to/site/assets/files/####/ [items] => Array ( [uploaded-filename.csv] => Array ( [url] => /site/assets/files/####/uploaded-filename.csv [filename] => /full/path/to/site/assets/files/####/uploaded-filename.csv ... [filedata] => Array ( [uploadName] => Uploaded-Filename.csv ) ) ) ) [type] => file ) ... ) Finally, I can get the basename of that uploaded file, build the correct path to the file with `destinationPath`, and use $files->rename() to rename it to the desired scheme: $form->processInput($this->input->post); // should add a check for $form->getErrors() here $field = $form->get('scores_upload'); $original_filename = $field->value->first()->basename(); $result = $this->files->rename( $field->destinationPath . $original_filename, $target_filename ); Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now