0

i want to host my files on aws s3 , files are being uploaded by client browser

i used to stream the files from my backend to s3 but there was lots of problem with large files

so i decided to create a pre signed upload url to directly upload the file from front

fornt will send the file to back end , back end will store the file information in database and creates a pre signed upload url and sends it back to the front

front will upload the file directly in s3 and notifies the back end , here is the first step / gathering information about the file / generating upload url / storing data in database

    $request->validate([
        'attachment'=>'required|string' ,
    ]);

    $original_name  = $request->input('attachment');
    $newName = 'some-versioning-info-'.$original_name ;

   $s3Upload = // store file data in database 
    
    list($client , $bucket ) = $this->getS3Client();


    $cmd = $client->getCommand('PutObject', [
        'Bucket' => $bucket,
        'Key'    => $newName
    ]);

    $request = $client->createPresignedRequest($cmd, '+20 minutes')->withMethod('PUT');
    $url = (string)$request->getUri();
    return response( ['url'=>$url , 'token' => $s3Upload->token );

front will upload the file with given url , and then will call this function to very upload and update the database

   function verifyUpload($token){

    $s3Upload = S3UploadUrl::where('token' , $token )->firstOrFail();

    if(!Storage::disk('s3')->exists($s3Upload->file_name))
        throw new ApiException("file not found!");

    $size = Storage::disk('s3')->size($s3Upload->file_name);
    if($size < 1  )
        throw new ApiException("something is wrong with the file");
        
    // all ok , store in database 

}

the problem is after upload is done , s3 only returns a boll value

enter image description here

even if frond doesnt send a file , and just send a empty PUT request to s3 it will return the same true value ... basically there is no way to check if the stored file is the same one that has been uploaded by client it could be some empty binary ... some additional info would have been nice

so my only option is to check the files size on back end in the verification function

    $size = Storage::disk('s3')->size($s3Upload->file_name);
    if($size < 1  )
        throw new ApiException("something is wrong with the file");

i was wondering if there is better way to check if the file has been compeltely uploaded and it's the same one as the uploaded ?

hretic
  • 999
  • 9
  • 36
  • 78
  • Why you submit the file to the server ? upload only to s3, and not both on your server and on s3, you can submit the metadata of the file if you want, but not the entire file – Lk77 Jun 13 '23 at 15:57
  • @Lk77 yeah sorry i change my previous upload code some left over codes ... i've updated the code to only receive the file name in the first step – hretic Jun 13 '23 at 16:00
  • i don't think that's a boolean, it's just the line numbers of postman – Lk77 Jun 13 '23 at 16:03
  • 1
    If you're concerned about the file being uploaded correctly, you can provide a [presigned URL with the Content-Length header signed](https://stackoverflow.com/questions/25991275/limit-size-of-objects-while-uploading-to-amazon-s3-using-pre-signed-url) so that S3 will fail with a 400 response if the file size isn't correct. – Anon Coward Jun 13 '23 at 17:42
  • @AnonCoward thanx good idea , also i can check the file size is the same before and after upload ... if there's no compression involved in s3 (i dont think there is any) ... would s3 store the corrupted/incomplete file on the server if the upload request gets interrupted and doesn't complete for some reason ? – hretic Jun 14 '23 at 09:19
  • 1
    Correct, S3 will not compress your data, and if you interrupt an upload with a that has a `Content-Length` header, the upload will be considered invalid, and S3 will return a malformed upload error message and toss out the data. – Anon Coward Jun 14 '23 at 13:42

0 Answers0