How about a little validations and
- sanitizing the path
- unique filename
- using streams
I made this function to handle the upload of a binary file via API, is there room for improvement?
public function upload(Request $request)
{
$binary = $request->getContent();
$tempFileName = tempnam('/tmp', 'tmp');
file_put_contents($tempFileName, $binary);
$storedFile = Storage::disk('public')->putFile('my-folder', new File($tempFileName));
unlink($tempFileName);
return $storedFile;
}
How about a little validations and
@azimidev I guess the putFile already uses a unique filename right?
can you elaborate a bit more on the sanitizing the path and using streams?
thanks you
@gssj85 yeah, putFile uses the stream, exactly. for path sanitization, if your path includes special chars such as / or _ or - they will be encoded in the URL so you need to escape them. Str::slug() is very useful I use. I see you ar using a static name $tempFileName but you should think about what will happen if you store the same file twice
@azimidev The $tempFileName turns into a new name with putFile(), it's just that I need to put the binary string into a file before passing it to putFile() because it doesn't accept the binary string directly.
It makes a copy with another unique name, then unlink() deletes the temporary file (also a unique generated name in /tmp with a prefix (sufix?))
Why don't you just use built in upload, eg. using multipart/form-data? Then you would just simply:
public function upload(Request $request)
{
$file = $request->file('name-of-your-file-field');
$storedFile = Storage::disk('public')->putFile('my-folder', $file->getContents());
return $storedFile;
}
@Yorki it's part of a challenge in the course I'm doing, I have done the form one now I the challenge is single route to uploae via rest api
@gssj85 but you could still use multipart/form-data via API and this is common practice. Like this is request like any other
anyway you could just go straight
$storedFile = Storage::disk('public')->putFile('my-folder', $request->getContent());
return $storedFile;
@Yorki that's a good one!
Though the putFile() accepted only a stance of File or UploadedFile as second parameter.
I'm giving it a try
@gssj85 not sure if it's documented, but it will accept also plain string of file, so you should be fine (as I used this in my project :]). However there is second method put I'm using:
$storedFile = Storage::disk('public')->put('my-folder', $request->getContent());
return $storedFile;
@Yorki I'm going to test this, following strictly documentation because I'm new no much other sources haha
Way I see in the docs the put method accepts a Resource as second paramenter (I think getContent(true) gets a resource? without it it's a plain string).
However the first parameter is the name of the file, different from the putFile() method which the first parameter is the directory path and the file name is autogenerated.
I think my fight here is wherever I should stop using framework helpers and use native php, like I'm using putfile() because of the facility of the unique name.
I have remade the function.
public function upload(Request $request)
{
$binaryData = $request->getContent();
$uniqueFileName = md5(uniqid(microtime(), true));
$fileExtension = substr(strrchr(getimagesizefromstring($binaryData)['mime'], '/'), 1);
$fileName = "$uniqueFileName.$fileExtension";
Storage::disk('public')->put("series_cover/$fileName", $binaryData);
return "series_cover/$fileName";
}
I figured that there was a possibility to generate a non unique name (remotely but yeah...).
Please or to participate in this conversation.