0

I am creating something like google drive or some cloud using PHP and HTML where you can save your files but i have problem with saving files to binary code and uploading it to database. I mean i want to do something like that:

User is uploading file by form in html -> converting file to binary -> saving it in database. User can download his file by some button or smh like that -> file is converting from binary to file.

I tried with doing a script what will save bin code in my database but when i am trying to send some files i am getting error like that:

Fatal error: Uncaught TypeError: fopen(): Argument #1 ($filename) must be of type string, array given in C:\xampp\htdocs\fileshub\src\send_file.php:12 Stack trace: #0 C:\xampp\htdocs\fileshub\src\send_file.php(12): fopen(Array, 'rb') #1 {main} thrown in C:\xampp\htdocs\fileshub\src\send_file.php on line 12

This is my form in html:

<form class="upload-form" action="./src/send_file.php" method="post" enctype="multipart/form-data"><br>
    <input type="text" name="filename" id="filename" placeholder="File name">
    <input type="file" name="file" id="file"><br>
    <button type="sumbit" class="submit">Submit</button>
</form>

And this is my script in php:

<?php
session_start();
include "../src/db_conn.php";

if(isset($_SESSION['id'])) {
    
  $id = $_SESSION['id']; // id usera
  $filename = $_POST['filename']; // nazwa pliku

  $file = $_FILES['file'];

  $data = fopen ($file, 'rb');
  $size = filesize ($file);
  $contents = fread ($data, $size);
  fclose ($data);

  $binfile = base64_encode($contents);

  if(!$filename|| !$file) {
    header("Location: ../index.php?error=Enter your data!");
    exit();
  } else {
    $check = "SELECT bin_code FROM files WHERE user_id = '$id' AND bin_code = '$binfile' AND file_name = '$filename'";
    $result = mysqli_query($conn, $check);

    if(mysqli_num_rows($result) === 1){
      header("Location: ../index.php?error=Your file exsist.");
      exit();
    }else {
      $save = "INSERT INTO files (user_id, file_name, bin_code) values('$id', '$filename', $binfile)";
      $saveresult = mysqli_query($conn, $save);
      $saveresult;
      header("Location: ../index.php?error=Your file has been saved");
      exit();
    }
  }
}
?>

db_conn:

<?php 
    $server = "localhost";
    $user ="root";
    $password = "";
    $db = "fileshub";

    $conn = mysqli_connect($server, $user, $password, $db);
?>

If you know any solutions for my problem please help :)

Files table Users table and example user

Z4-tier
  • 7,287
  • 3
  • 26
  • 42
Qbiter
  • 1
  • 1
  • Don't stores the files in the database. Store them in the "file" system and just store the metadata in the db. Add a checksum to your metadata and use that for checking whether the file has already been uploaded. – user1191247 Nov 21 '22 at 22:47
  • I think $file variable should be $file = $_FILES['file']['tmp_name']; but storing them in the database is a bad idea. Instead, use the file system for that and store the location instead. – Dave Nov 21 '22 at 22:50
  • @nnichols But if i will store files on system other users can get access by typing location.. I mean if all files will be in files/users/file.jpg... anyguy can get access to this. I don't want it. If there is a way to save files on other server disk it will be good option. – Qbiter Nov 21 '22 at 22:52
  • @Dave It is what am i saying at comment above. If there is way to save files on other server disk.. It can be good idea but i still don't know how to do this :/ – Qbiter Nov 21 '22 at 22:54
  • You should save the files outside of your webroot and then you can easily control access to them. That way the file can still be requested via your application which can do basic auth checks before returning the file. Search on SO. There are plenty of questions about serving files via PHP - https://stackoverflow.com/questions/3697748/fastest-way-to-serve-a-file-using-php – user1191247 Nov 21 '22 at 23:01
  • @nnichols I have my own script to save files... but how to save files on path out of webroot? There is my problem. – Qbiter Nov 21 '22 at 23:15
  • Assuming your webroot is something like `/var/www/mywebsite` then store the uploaded files in `/var/media/uploads` or similar. Just remember to make sure your web server user has appropriate permissions on the folder you want to use - [move_uploaded_file](https://www.php.net/manual/en/function.move-uploaded-file.php) – user1191247 Nov 22 '22 at 00:00

2 Answers2

0

I believe you know that uploading an image to a directory is a more efficient way to store it.

Please note that $_FILES['file'] is an array containing all sorts of information of the uploaded file, for your case you have to use the filename of the uploaded file. (which is "tmp_name")

So change

 $file = $_FILES['file'];
 $data = fopen ($file, 'rb');

to

 $file = $_FILES['file']["tmp_name"];
 $data = fopen ($file, 'rb');

On the other hand, an alternative way is to use file_get_contents instead of fopen, fread, etc.

$contents = file_get_contents($_FILES['file']["tmp_name"]);
Ken Lee
  • 6,985
  • 3
  • 10
  • 29
  • I done it.. now i am trying to do a system where i will be abled to download file from database. I started with decoding file and it's working but how to download it as file? I tried to save decoded file in folder but i got a lot of errors. This is my script: https://pastebin.com/VpqaQ6WG Do you know any solutions? – Qbiter Nov 22 '22 at 19:29
  • Good to know that you have done it. For "downloading", please post another question so that we can answer it. Thanks – Ken Lee Nov 22 '22 at 19:35
0

So firstly you need to ensure you have a directory that PHP has access and has permissions on but that is not publicly accessible. Usually, on web hosts the web root folder is a sub folder of the home directory, so you can create a new folder there for file storage. Eg:

/home/myuser/public_html/ <-- might be the web root (some installations differ eg: htdocs or html or httpdocs)
/home/myuser/files/ <-- Create this folder for storing files.

Alternatively, if youre web server is Apache, you can create a folder inside your web root, and protect that folder using a .htaccess file

The easiest way then to store an uploaded file on the file server is to use the move_uploaded_file command that PHP provides, here is how I would achieve this:

$postname = 'file';
$root = '/home/myuser/files';

//cleanse the filename to prevent SQL injections when saving to DB
$filename = preg_replace("/[^a-zA-Z0-9\.]/","_",$_FILES[$postname]['name']);

$path = "$root/$filename";

//Create the files folder if it doesnt already exist...
if(!file_exists($root)) if(!mkdir($root,0775,true)) die("Failed to create root folder $root");

//Store the uploaded file in the files folder
if(!move_uploaded_file($_FILES[$postname]['tmp_name'],$path)) die('Failed to move uploaded file into asset storage');

//Store the file location in the database...
$saveresult = mysqli_query($conn,"INSERT INTO `files` (`filename`,`path`) VALUES ('$filename','$path')");
Dave
  • 386
  • 2
  • 8