Change storage folder on file upload - typo3

I have form with fields like
'name, firstname, street, zip, city and image'.
The image was an upload
field. Everything works fine, i can upload the image as Filereferrence. But the image was uploaded every time into "fileadmin/". I want to upload the image into "/uploads/<extensionname>" or "fileadmin/user_uploads/<extensionname>".
The part where the upload and file moving was realized look like.
$storageRepository = $this->objectManager->get('TYPO3\\CMS\\Core\\Resource\\StorageRepository');
$storage = $storageRepository->findByUid('1');
$fileData = array();
$fileData['name'] = $_FILES['tx_oaevents_eventslisting']['name']['image'][0];
$fileData['type'] = $_FILES['tx_oaevents_eventslisting']['type']['image'][0];
$fileData['tmp_name'] = $_FILES['tx_oaevents_eventslisting']['tmp_name']['image'][0];
$fileData['size'] = $_FILES['tx_oaevents_eventslisting']['size']['image'][0];
$newFileObject = $storage->addFile(
$fileData['tmp_name'], $storage->getRootLevelFolder(), $fileData['name']
);
This line deines the storage folder form database:
$storage = $storageRepository->findByUid('1');
which is fileadmin as default. But what is the best way to change/modify this storage folder destination?

If you want to specify the destination folder for your upload, I suggest you take a look at the FAL File Upload example from Helmut Hummel. For his example, there is also a blogpost which describes how the file upload works and why you should use a TypeConverter for FAL file upload in TYPO3 6.2+
I have implemented the solution several times and it works just great, since it covers a lot of scenarios you may run into when implementing a file upload (e.g. validation, error handling, file replacement if file exists)

Related

Laravel upload image is using intervention image and generate unique name

I'm using laravel 5.8 and intervention image to upload and resize an image.
I want to store this in storage/app/public/images folder and I'm trying to use the storage facade to auto generate a unique name but the following doesn't work:
$file = $request->file('file');
$image = Image::make($file->getRealPath())->resize(360, 180);
Storage::disk('public')->putFile('images', $image->getEncoded());
Is it possible to auto generate unique file name using the storage facade for images similar to the when you upload normal files as follows:
Storage::disk('local')->putFile('forms', $request->file('file'));
Uploaded files use temporary file names when uploaded in your application. These can serve as unique names you can use to save.
You can access this using the ->getPathName() method of the uploaded file.
Alternatively, you can use ->getClientOriginalName() for the original name of the file.
With Intervention/Image, you can use the ->save() method to save this image to the destination folder:
$file = $request->file('file');
$image = Image::make($file->getRealPath())
->resize(360, 180)
->save(storage_path('app/public/images/'.$file->getPathName());
I haven't tested this but I hope this helps.
$image = Image::make($request->file('file'))->resize(360, 180)
->save(storage_path('app/public/images/'.$file->getPathName());

Uploading file to storage without extension

I am trying to create an app where users can upload files to the "wall". The idea is not important. Each file is added both to storage and to database as [fileName : url) under user's profile. Because of limitations regarding strings in database, I keep filenames without extensions (can't use dot symbol). Uploading works fine but I have a problem with deletion. Based on the file user picks to delete in app I get the filename(without extension). My delete function should delete the file from storage but it cannot locate file because of missing extension.
I use this function to upload the data:
let uploadTask = ref.putData(contents as Data, metadata: myMetadata, completion: { (metadata, error) in ...}
and the file itself:
let contents = try Data(contentsOf: url.standardizedFileURL)
Is it possible to upload "contents" without the extension? Or maybe is there another approach I'm missing?
Thanks for tips.
It's not a really good idea to store the names of random things (including files) as keys in Realtime Database. You could make this easier on yourself by pushing an object at a location in the database for each file uploaded. The pushed object could contain the name and location of the file in Storage, along with any other metadata about that file, and you won't have to mangle that data as long as it's stored in values rather than keys.

Upload same name files to google cloud storage then download them with original names

So in google-cloud-storage if you upload more than one file with the same name to it the last will overwrite what was uploaded before it.
If I want to upload more than one file with the same name I should append some unique thing to the file name e.g. timestamp, random UUID.
But by doing so I'll lose the original file name while downloading, because I want to serve the file directly from google.
If we used the unique identifier as a folder instead of appending it to the file name, e.g. UUID +"/"+ fileName then we can download the file with its original name.
You could turn on Object Versioning which will keep the old versions of the object around.
Alternatively, you can set the Content Disposition header when uploading the object, which should preserve whatever filename you want on download.
instead of using object versioning, you can attach the UUID (or any other unique identifier) and then update the metadata of the object (specifically the content disposition), the following is a part of a python script i've used to remove the forward slashes - added by google cloud buckets when to represent directories - from multiple objects, it's based on this blog post, please keep in mind the double quotes around the content position "file name"
def update_blob_download_name(bucket_name):
""" update the download name of blobs and remove
the path.
:returns: None
:rtype: None
"""
# Storage client, not added to the code for brevity
client = initialize_google_storage_client()
bucket = client.bucket(bucket_name)
for blob in bucket.list_blobs():
if "/" in blob.name:
remove_path = blob.name[blob.name.rfind("/") + 1:] # rfind gives that last occurence of the char
ext = pathlib.Path(remove_path).suffix
remove_id = remove_path[:remove_path.rfind("_id_")]
new_name = remove_id + ext
blob.content_disposition = f'attachment; filename="{new_name}"'
blob.patch()

Moodle File API : multiple rows?

In a Moodle form I perform a file upload using the filemanager element:
$mform->addElement('filemanager', 'attachment',get_string('displayedcontent', 'block_helloworld'), null, $filemanageropts);
Once the form is validated, when I record my instance in the database, I also save the uploaded file using the following function:
file_save_draft_area_files($form_submitted_data->attachment, $context->id, 'block_helloworld', 'attachment',
$form_submitted_data->attachment, array('subdirs' => 0, 'maxbytes' => 500000, 'maxfiles' => 1));
This is working fine but when I take a look at the DB table mdl_files, I saw that for my file there are 4 rows:
component fileare itemid filepath filename
block_helloworld attachment 706783489 / .
block_helloworld attachment 706783489 / test5.pdf
user draft 706783489 / .
user draft 706783489 / test5.pdf
There are 2 rows for my uploaded file in my component block_helloworld and in the component user.
One row has a filename but not the other one!
This sounds strange. Is that normal?
When I perform file deletion, how to delete all these files?
Note: I am using moodle v3.0.6
As far as I remember, this is normal behaviour. I had this issue, too, but when you cross check (like doing a file upload into a course) you will notice that there are 2 rows, too. Not sure, why but for me it was normal behaviour
The 4 entries are:
The folder that your file is in
The file itself
The folder that the draft version of the file is stored in whilst the form is being edited
The draft file whilst the form is being edited
The draft files will be automatically cleaned up after a day or so.

Get path of uploaded image in Moodle

I have added custom column to store company logo. I have used file api of moodle like :
$mform->addElement('filepicker', 'certificatelogo', 'Company Logo', null,
array('maxbytes' => $maxbytes, 'accepted_types' => '*'));
$mform->setDefault('certificatelogo', '0');
$mform->addHelpButton('certificatelogo', 'certificatelogo', 'certificate');
Once the form is submitted itemid will be stored in custom column. Say "648557354"
Now I need to get image to print logo on certificate. How can I get image path from itemid? Do I need to store any other information to retrieve image?
The itemid returned is the temporary id of the draft area where the file is stored whilst the form is being displayed. You need to copy the file into its 'real' location, when the form is submitted, otherwise the file will be automatically deleted after a few days (and it will only be accessible to the user who originally uploaded it).
I'd always recommend using the filemanager element, if you are planning on keeping the file around (filepicker elements are for files you want to process and discard, such as when uploading a CSV file data to parse and add to the database).
Details of how to use it are here:
https://docs.moodle.org/dev/Using_the_File_API_in_Moodle_forms#filemanager
But the basic steps are:
Copy any existing files from the 'real' area to the draft area (file_prepare_standard_filemanager).
Display the form.
On submission, copy files from the draft area to the 'real' area (file_postupdate_standard_filemanager).
When you want to display the file to the user, get a list of files stored in the file area (defined by the component, filearea, context and, optionally, itemid, you used in file_prepare_standard_filemanager and file_postupdate_standard_filemanager). You can do this with: $fs = get_file_storage(); $fs->get_area_files().
For those files (maybe only 1 file, in your case), generate the URL with moodle_url::make_pluginfile_url.
Make sure your plugin has a PLUGINNAME_pluginfile() function in lib.php, to examine incoming file requests, do security checks on them, then serve the file.
There is a reasonable example of all of this at: https://github.com/AndyNormore/filemanager