In this article, we will discuss 2 ways how you can loop through a number in React.
While developing frontend of an application π₯, you might encounter a situation where you have to display a list of data. For example, a list of users etc.
Most common way to loop through an array in React is using Javascript built-in map function.
But if you have a number that you have to loop through. For example, run a loop till 10 etc.
In this case, we have 2 options.
1st way: Using function βοΈ
One way to loop through a number in React is to create a function that will:
Create an array.
Using basic for loop and push the HTML code in array.
Return the array.
Here is the code on how to do that. π¨π»βπ»
function App() {
const [number, setNumber] = React.useState(10);
function renderLoop() {
const elements = [];
for (let a = 0; a < number; a++) {
elements.push(
<p key={ `1st-way-${ a }` }>{ a }</p>
);
}
return elements;
}
return (
<>
{ renderLoop() }
</>
);
}
Following will be the output of above code:
0
1
2
3
4
5
6
7
8
9
2nd way: Using map β
Javascript’s map function can also be used to iterate over an array and display a list without having to create a function.
function App() {
const [number, setNumber] = React.useState(10);
return (
<>
{ Array.from({ length: number }, function (_, index) { return index })
.map(function (n) {
return (
<p key={ `2nd-way-${ n }` }>{ n }</p>
)
}) }
</>
);
}
Explanation π΅π»ββοΈ
The first argument of Array.from is an object that will create an array of length 10 such that each element has an index starting from 0.
The second argument is a mapping function.
First parameter is “_” which means the value.
Second parameter is “index”.
It is returning the index without any modification, so the original number will be returned.
It will create an array from 0 to 9.
Using the map function, you can perform some action on that array created from number. In this case, we are displaying each number n in a paragraph. π
So that’s how you can loop through a number in React. If you face any problem in following this, kindly do let me know. π¬
In this tutorial, we will learn how you can get updated value from child component to parent component in React.
Let’s say you have a parent child component in your React app. You are sending data from parent to child and your child component is updating that variable’s value. Now when you get the value in parent component, you still get the original value, not the updated one.
First, you need to create a reference and pass it to the child component.
function Parent() {
// Create a reference
const childRef = React.useRef();
// Create array of users
const [users, setUsers] = React.useState([
{ id: 1, name: "Adnan" },
{ id: 2, name: "Afzal" }
]);
// Function to get updated users
function getUsers() {
// Get users with reference
let tempUsers = [];
if (childRef.current) {
tempUsers = childRef.current.getUsers();
}
console.log({
"users": users,
"tempUsers": tempUsers
});
}
// Set child component and pass users array to it
return (
<>
<Child users={ users }
ref={ childRef } />
{/* Button to get users */}
<button type="button" onClick={ function () {
getUsers();
} }>Get users</button>
</>
);
}
childRef: First, we are creating a reference.
users: Then we are creating a state variable.
getUsers(): A function is created that will get the state value using reference.
We are passing the users array and reference to the child component.
A button is also created which when clicked, will call the function to get the state variable.
Then in your child component, you need to create it using forwardRef.
// Create child component that gets properties
// Export child using forward reference
const Child = React.forwardRef(function (props, ref) {
// Get users from parent component
const [users, setUsers] = React.useState(props.users || []);
// Use imperative handler to return updated value
React.useImperativeHandle(ref, function () {
return {
getUsers() {
return users;
}
};
});
// Function to set user name to "Khalid" where user ID is 1
function updateUser(id, name) {
const tempUsers = JSON.parse(JSON.stringify(users));
for (let a = 0; a < tempUsers.length; a++) {
if (tempUsers[a].id == id) {
tempUsers[a].name = name;
break;
}
}
setUsers(tempUsers);
}
// Create button to update user
return (
<>
<button type="button" onClick={ function () {
updateUser(1, "Khalid");
} }>Update user</button>
</>
);
});
forwardRef: It is used to pass ref from parent component to child component.
Then creating a state variable and initialize it with props value received from parent component.
We are using imperative handler to return the updated value.
A button is created in child component that updates the value using it’s ID.
JSON.parse(JSON.stringify(users)): We are first converting the users array to JSON, then converting back to Javascript array. This ensures a deep copy.
That’s how you can get updated value from child component to parent component in React.
In this tutorial, we will show you, how you can do pagination in your React app having Node.js and MongoDB as backend. Even if you have any other backend technology, you can still get the algorithm and apply it in your language.
React
Following is our React component that will call an AJAX request and fetch the data from API. After fetching the data from API, it will render the data along with the pagination links. Whenever any of the pagination link is clicked, it will refetch the data based on the clicked page number.
<script src="js/babel.min.js"></script>
<script src="js/react.development.js"></script>
<script src="js/react-dom.development.js"></script>
<div id="app"></div>
<script type="text/babel">
function App() {
// Set current page
const [page, setPage] = React.useState(1);
// Number of pages on pagination
const [pages, setPages] = React.useState(0);
// Whenever it's value is updated, the data will be re-fetched
const [refetch, setRefetch] = React.useState(0);
// Data array
const [users, setUsers] = React.useState([]);
// Check if there are more pages
const [hasMorePages, setHasMorePages] = React.useState(false);
async function loadMore() {
// Creating a built-in AJAX object
var ajax = new XMLHttpRequest();
// Tell the method, URL of request and make is asynchronous
ajax.open("POST", "http://localhost:3000/fetch-users", true);
// Detecting request state change
ajax.onreadystatechange = function () {
// Called when the response is successfully received
if (this.readyState == 4) {
if (this.status == 200) {
// For debugging purpose only
// console.log(this.responseText);
// Converting JSON string to Javasript array
var response = JSON.parse(this.responseText);
// Update state variable
setUsers(response.users);
// Set if there are more pages
setHasMorePages(response.hasMorePages);
// Set pagination
setPages(response.pages);
}
}
};
// Create form data object
const formData = new FormData();
// Attach current page number
formData.append("page", page);
// Send the request
ajax.send(formData);
}
// Run function when page value updates
React.useEffect(function () {
loadMore();
}, [refetch]);
return (
<>
{/* Display data */}
{ users.map(function (user) {
return (
<p key={ `user-${ user._id }` }>{ user.name }</p>
);
}) }
{/* Show pagination if required */}
{ pages > 1 && (
<nav>
<ul>
{ Array.from({ length: pages }, function (_, index) { return index + 1 } ).map(function (p) {
return (
<li key={ `pagination-${ p }` } className={ `page-item ${ p == page ? "active" : "" }` }>
<a href="#" onClick={ function (event) {
event.preventDefault();
setPage(p);
setRefetch(refetch + 1);
} }>{ p }</a>
</li>
);
}) }
</ul>
</nav>
) }
</>
);
}
ReactDOM.createRoot(
document.getElementById("app")
).render(<App />);
</script>
Node.js and MongoDB
Now in our Node.js server, we will create an API that will return all the records based on the current page from client side. It will also return the number of pagination links.
That’s how you can create pagination links in your React app with Node.js and MongoDB as backend. If you face any problem in following this, feel free to contact me.
Previously, we wrote 2 articles on how to add a “load more” button. First article uses Node.js and MongoDB and EJS for frontend and second article uses PHP and MySQL. In this article, we will show you, how you can create a “load more” button in React with Node.js and MongoDB as your backend. This is the refined version of previous load more tutorial in Node.js and MongoDB.
First, let me show you all the code. Then I will explain everything.
React
function App() {
// Set current page
const [page, setPage] = React.useState(1);
// Data array
const [users, setUsers] = React.useState([]);
// Check if there are more pages
const [hasMorePages, setHasMorePages] = React.useState(false);
async function loadMore() {
// Creating a built-in AJAX object
var ajax = new XMLHttpRequest();
// Tell the method, URL of request and make is asynchronous
ajax.open("POST", "http://localhost:3000/fetch-users", true);
// Detecting request state change
ajax.onreadystatechange = function () {
// Called when the response is successfully received
if (this.readyState == 4) {
if (this.status == 200) {
// For debugging purpose only
// console.log(this.responseText);
// Converting JSON string to Javasript array
var response = JSON.parse(this.responseText);
// Get data from API
const newArr = response.users;
// β Less efficient, more readable
// Get current data
/*const tempArr = [ ...users ];
// Loop through all new records
for (let a = 0; a < newArr.length; a++) {
// And add them in existing array
tempArr.push(newArr[a]);
}
// Update state variable
setUsers(tempArr);*/
// β Efficient way
setUsers([...users, ...newArr]);
// Set if there are more pages
setHasMorePages(response.hasMorePages);
}
}
};
// Create form data object
const formData = new FormData();
// Attach current page number
formData.append("page", page);
// Send the request
ajax.send(formData);
}
// Run function when page value updates
React.useEffect(function () {
loadMore();
}, [page]);
return (
<>
{/* Display data */}
{ users.map(function (user) {
return (
<p key={ `user-${ user._id }` }>{ user.name }</p>
);
}) }
{/* Show load more button if there are more pages */}
{ hasMorePages && (
<button type="button"
onClick={ function () {
// Increment page value
// It will automatically call the loadMore function from useEffect hook
setPage(page + 1);
} }>Load more</button>
) }
</>
);
}
Here, we are displaying all the data we are getting from API. We are displaying the “load more” button only if there are more pages required. We created a React.useEffect hook and calling the loadMore function everytime the page value gets updated. It will automatically gets called first time when the page loads. After that, every time you click the “Load more” button, we are simply incrementing the page value by 1. It will trigger the React.useEffect hook, thus calling the loadMore function again.
From API, we will receive the data that will be an array, and a boolean variable that tells if there are more pages required. Based on the latter, we will show or hide the “Load more” button. If there are more pages required, you can keep pressing load more button. When there are no more records in the database, then the load more button will be removed.
When the response from API is received, we are appending the new data in our existing data array. The way to do that in React is different. First, we need to create a shallow copy of our existing array using spread operator: const tempArr = [ β¦users ]; Then we need to loop through all new data received from API, and push it in your shallow copy of array. Finally, we will update our state variable and will render the new data.
For rendering, we are using Javascript map function to iterate over an array. In each paragraph, we should have a unique key value for React to identify each element uniquely. In order to create a unique key, we are using user ID, and we are displaying user name in each paragraph. This is create a “load more” button in our React component. In next step, we will create it’s API.
Node.js & MongoDB
// Run command in your terminal:
// npm install express http mongodb cors express-formidable
const express = require("express");
const app = express();
const http = require("http").createServer(app);
const mongodb = require("mongodb");
const ObjectId = mongodb.ObjectId;
const MongoClient = mongodb.MongoClient;
const cors = require("cors");
app.use(cors("http://localhost/load-more.html"));
// Native way to allow CORS
/*// Add headers before the routes are defined
app.use(function (req, res, next) {
// Website you wish to allow to connect
res.setHeader("Access-Control-Allow-Origin", "*");
// Request methods you wish to allow
res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS, PUT, PATCH, DELETE");
// Request headers you wish to allow
res.setHeader("Access-Control-Allow-Headers", "X-Requested-With,Content-Type,Authorization");
// Set to true if you need the website to include cookies in the requests sent
// to the API (e.g. in case you use sessions)
res.setHeader("Access-Control-Allow-Credentials", true);
// Pass to next layer of middleware
next();
});*/
const expressFormidable = require("express-formidable");
app.use(expressFormidable({
multiples: true
}));
const port = process.env.PORT || 3000;
const databaseName = "test"
const MONGO_URI = process.env.MONGO_URI || "mongodb://127.0.0.1:27017";
http.listen(port, async function () {
console.log("Server started");
const client = new MongoClient(MONGO_URI);
try {
await client.connect();
const db = client.db(databaseName);
console.log("Database connected.");
// Seeding the data in database
/*const usersCount = await db.collection("users").countDocuments({});
if (usersCount == 0) {
await db.collection("users")
.insertMany([
{ name: "Adnan" },
{ name: "Afzal" },
{ name: "Ahmad" },
{ name: "Khalid" },
{ name: "Tariq" },
]);
}*/
app.post("/fetch-users", async function (request, result) {
const limit = 1;
const page = parseInt(request.fields.page || 1);
const skip = (page - 1) * limit;
const users = await db.collection("users")
.find({})
.sort({
_id: 1
})
.skip(skip)
.limit(limit)
.toArray();
const usersArr = [];
for (let a = 0; a < users.length; a++) {
const obj = {
_id: users[a]._id || "",
name: users[a].name || ""
};
usersArr.push(obj);
}
const totalCount = await db.collection("users").countDocuments({});
const hasMorePages = (page * limit) < totalCount;
result.json({
status: "success",
message: "Data has been fetched.",
users: users,
hasMorePages: hasMorePages
});
});
} catch (exp) {
console.log(exp.message);
}
});
Here, we are first starting our server and connecting with MongoDB database. We created an API that accepts the page number as parameter. If the page number is not provided, then the default value of it will be 1. We are setting the limit to 1 for testing. We subtract 1 from current page value and multiply it by the limit, it will give use the number of records we need to skip.
Then we are fetching the data from database using skip and limit. Your document might have a lot of fields, so we created an obj to only return those fields that are need for this API. Finally, in order to check if there is a need for more pages, we first need to find the total number of records in our collection. We can then check if it is greater than the product of limit and page variable. If it is greater, it means there are still more records in the database.
That’s how you can create a “load more” button in React as your frontend and Node.js and MongoDB as your backend. If you face any problem in following this, kindly do let me know.
If you are working in React and are fetching data from an API that is returning some content with mixed HTML entities. You will notice that when you are rendering the HTML data in React, the HTML entities does not gets rendered properly. It is because React does not parse HTML entities by default.
Today, we will show you a way that let’s you parse HTML entities in React. First, let’s say we have a following React component that displays a text having an HTML entity.
You can also download this JS file and paste in your project and use relative path. Finally, you need to call the “HTMLReactParser(var string)” function and send your variable as an argument.
{ HTMLReactParser(myVar) }
If you run the page now, you will see that your HTML entity has been parsed properly.
In this article, we will teach you how you can use a callback function to be called from child parent that will invoke a function in parent component in React JS.
Let’s say you have:
A parent component that has an array.
You are looping through an array and displaying the data using child component.
You want to call a function from child component that will invoke a function in parent component.
Here, we have a React parent component that has an array of data. Each array element has an ID, name and age. You might be receiving this data from API. In each loop iteration, it is rendering a child component.
key: This is used by React JS to uniquely identify an element.
d: This is the property value parent component is sending to the child component.
What are props in React JS ?
props (properties): Props are used in React JS to pass the data from parent component to child component. They are read-only so child component cannot modify the value of “d”.
Now, let’s assume you want to have a delete function in child component that, when called, will call a function in parent component. So that the parent component that perform an action on that child. In this case, we will remove that array element from “data” array in parent component.
So first, we will create a delete button in child parent. Once that button is clicked, we will call a function we will receive in props from parent component.
Finally, we will create that function in parent component that will search the array element using ID and remove it from array. At the end, we will update the React state variable as well.
function onDelete(id) {
const tempArr = [ ...data ];
for (let a = 0; a < tempArr.length; a++) {
if (tempArr[a].id == id) {
tempArr.splice(a, 1);
break;
}
}
setData(tempArr);
}
I was looking for a tool that allows me to write API documentation so I can provide it to the frontend developers and also for myself. I checked many but didn’t find any that fits to all of my requirements. So I decided to create one of my own. Creating my own tool gives me flexibility to modify it as much as I want.
I also wanted it to share it with other developers who might be having problem in finding the tool to write documentation for their API. So I uploaded it on Github and it is available for anyone for free.
How to write API documentation
A tool is created in PHP and MySQL that allows developers to write API documentation, and this tool is available for free. You can create multiple sections to group the APIs based on modules. For example, user authentication, user posts, comments, replies can be separate sections.
To write each API, you need to tell:
The section where it goes.
The name of the endpoint. It can be the URL of API.
The method, it can be either GET or POST. But since you will have the code, you can add more methods as per your needs.
Add a little description about the API, for example what this API does.
Headers:
You need to tell the key of header, whether it is required or optional. And a little description about the header, for example, it’s possible values.
Parameters:
Parameters are usually send in the URL. You can define them along with their key, and value and whether they are optional or not.
Arguments:
For defining the arguments, you need to specify it’s type too. Whether it can be an integer, a string, boolean value or a file object.
Example request body. You can write the CURL code inside it to give an example.
Status codes and their responses.
I wrote a complete documentation of a project using this tool. You can check that from here.
I created an online free FTP manager in PHP that allows developers to work on their projects from anywhere. I created this tool in PHP and MySQL using Laravel framework. The frontend is designed in Bootstrap and React JS.
Let’s discuss each feature and I will also show you how I built this.
What you will learn:
Connect with FTP.
List files from FTP directory.
Fetch file content.
Edit FTP file.
Create a new file.
Create a new folder.
Upload files.
Download files.
Rename file.
Delete file.
Delete folder.
We created a PHP class named “FTP” in a file called “FTP.php”. All our functions will go in that class.
1. Connect with FTP
The first step is to connect with FTP server. Following code will create a function that will connect with your FTP server (we are not calling it yet).
class FTP
{
private $conn_id = null;
private $server = "";
private $username = "";
private $password = "";
private function do_connect()
{
try
{
// Establishing connection
$this->conn_id = ftp_connect($this->server);
if (!$this->conn_id)
{
echo json_encode([
"status" => "error",
"message" => "Could not connect to " . $this->server
]);
exit();
}
// Login with username and password
$login_result = ftp_login($this->conn_id, $this->username, $this->password);
if (!$login_result)
{
echo json_encode([
"status" => "error",
"message" => "Wrong password for '" . $this->username . "'."
]);
exit();
}
// Enable passive mode for better compatibility
ftp_pasv($this->conn_id, true);
}
catch (\Exception $exp)
{
echo json_encode([
"status" => "error",
"message" => "Could not connect to " . $this->server
]);
exit();
}
}
}
Comments has been added with each line for explanation. Make sure to enter your correct FTP server address, FTP account’s username and its password. In the next step, we will call this function to connect with FTP server.
2. List files from FTP directory
The next step is to list all files from FTP directory. Create the following function in your FTP class.
public function fetch_files()
{
$this->do_connect();
$path = "/directory-name";
// Get file listing
$file_list = ftp_nlist($this->conn_id, $path);
if ($file_list === false)
{
echo json_encode([
"status" => "error",
"message" => "Error retrieving file list."
]);
exit();
}
$files = [];
foreach ($file_list as $file)
{
$obj = [
"file" => $file,
"size" => ftp_size($this->conn_id, $file)
];
if ($obj["file"] != "." && $obj["file"] != "..")
{
array_push($files, $obj);
}
}
// Close the connection
ftp_close($this->conn_id);
echo json_encode([
"status" => "success",
"message" => "Data has been fetched.",
"files" => $files
]);
exit();
}
This function will first connect with the FTP server.
Then it will fetch all the files from $path variable.
If the directory does not exists or if it does not have read permission, then it will return an error.
All files from that directory will be put in an array along with the size of the file in bytes.
If it is a directory, then it’s size will be -1.
Finally, it returns the array with the response.
3. Fetch file content
Reading the content of FTP file is necessary because in order to edit the file, we need to first view the file. Following function will fetch the content of file and return it in response.
public function fetch_content()
{
$this->do_connect();
$file = "/directory-name/file-name.php";
// Local path for downloading the file
$local_file = tempnam(sys_get_temp_dir(), 'ftp_download');
// Download the file from FTP server to local file
if (!ftp_get($this->conn_id, $local_file, $file, FTP_BINARY))
{
echo json_encode([
"status" => "error",
"message" => "Failed to read '" . $file . "'"
]);
exit();
}
// Read contents of the local file
$file_content = file_get_contents($local_file);
// Display or process the file content as needed
if ($file_content === false)
{
echo json_encode([
"status" => "error",
"message" => "Failed to read file content."
]);
exit();
}
// Clean up: Delete the temporary local file
unlink($local_file);
echo json_encode([
"status" => "success",
"message" => "Data has been fetched.",
"content" => $file_content
]);
exit();
}
It will first download the file in a temporary directory to your server.
If the file does not exists, then it will return an error.
It will return an error if it fails to read the FTP file.
Usually it is because if the $path variable is a directory or an image or document file.
After the file’s content is fetched, we will remove the temporary file from our server.
4. Edit FTP file
After the file’s content is successfully fetched, the next step is to update the file. You are working in FTP, editing the code is what you will be doing most of the time.
Updating the content of file requires 2 steps:
Saving the file in temporary folder.
Uploading the temporary file on FTP server.
public function update_content()
{
$this->do_connect();
$file = "/directory-name/file-name.php";
$content = "console.log(\"Hello world\")";
// Local path for downloading the file
$local_file = tempnam(sys_get_temp_dir(), 'ftp_download');
// Write the new content to a local temporary file
file_put_contents($local_file, $content);
if (!ftp_put($this->conn_id, $remote_file, $local_file, FTP_ASCII))
{
echo json_encode([
"status" => "error",
"message" => "There was a problem updating '" . $remote_file . "'"
]);
exit();
}
unlink($local_file);
// Close the FTP connection
ftp_close($this->conn_id);
echo json_encode([
"status" => "success",
"message" => "File has been updated."
]);
exit();
}
5. Create a new file
Creating a new file in FTP in PHP is as simple as updating the file. We just need to set the content of file as empty string. So we will be uploading an empty file to FTP server.
public function create_file()
{
$this->do_connect();
$path = "/directory-name";
$name = "file-name.php";
// Local file content to be uploaded
$file_content = "";
// Local path for downloading the file
$local_file = tempnam(sys_get_temp_dir(), 'ftp_download');
// Write the content to a temporary local file
file_put_contents($local_file, $file_content);
// Remote file path where the file will be created
$remote_file = $path . "/" . $name; // Replace with the desired remote file path
// Upload the local file to the FTP server
if (!ftp_put($this->conn_id, $remote_file, $local_file, FTP_ASCII))
{
echo json_encode([
"status" => "error",
"message" => "There was a problem while creating '" . $name . "'"
]);
exit();
}
unlink($local_file);
// Close the FTP connection
ftp_close($this->conn_id);
echo json_encode([
"status" => "success",
"message" => "Successfully created '" . $name . "'"
]);
exit();
}
Create a temporary empty file on local directory.
Upload it to FTP.
Remove the file from local directory.
6. Create a new folder
Creating a folder is must easier than creating a file on FTP server.
public function create_folder()
{
$this->do_connect();
$path = "/directory-name";
$name = "folder-name";
$folder = $path . "/" . $name;
if (!ftp_mkdir($this->conn_id, $folder))
{
echo json_encode([
"status" => "error",
"message" => "There was a problem while creating '" . $name . "'"
]);
exit();
}
echo json_encode([
"status" => "success",
"message" => "Successfully created '" . $name . "'"
]);
exit();
}
Note: It will return an error if the directory already exists.
7. Upload files
To upload the file from local computer to FTP server, you need to first save it in your local server. Then upload the file to FTP server. After it is successfully uploaded, you can remove the file from local server.
public function upload()
{
$this->do_connect();
$path = "/directory-name";
$file_name = basename($_FILES["file"]["name"]);
$target_file = "uploads/" . $file_name;
if (!move_uploaded_file($_FILES["file"]["tmp_name"], $target_file))
{
echo json_encode([
"status" => "error",
"message" => "The file " . htmlspecialchars(basename( $_FILES["file"]["name"])) . " has been uploaded."
]);
exit();
}
if (!ftp_put($this->conn_id, $file_name, $target_file, FTP_ASCII))
{
echo json_encode([
"status" => "error",
"message" => "There was a problem updating '" . $file_name . "'"
]);
exit();
}
// Close the FTP connection
ftp_close($this->conn_id);
echo json_encode([
"status" => "success",
"message" => "File(s) has been uploaded."
]);
exit();
}
If you are working in Laravel, your upload function should be like this:
public function upload()
{
$this->do_connect();
$path = "/directory-name";
$files = request()->file("files");
foreach ($files as $file)
{
$remote_file = $file->getClientOriginalName();
$file_path = "ftp/" . $file->getClientOriginalName();
$file->storeAs("/private", $file_path);
if (!ftp_put($this->conn_id, $remote_file, storage_path("app/private/" . $file_path), FTP_ASCII))
{
return response()->json([
"status" => "error",
"message" => "There was a problem updating '" . $remote_file . "'"
]);
}
Storage::delete("private/" . $file_path);
}
// Close the FTP connection
ftp_close($this->conn_id);
return response()->json([
"status" => "success",
"message" => "File(s) has been uploaded."
]);
}
8. Download files
Downloading the file to local computer requires 2 steps.
First is to download the file on local server from FTP server.
Then download it to local computer from local server.
Download file from FTP to local server
Following code will be used to download the file on local server.
public function download()
{
$this->do_connect();
$path = "/directory-name";
$file = "file-name.php";
// Local path for downloading the file
$local_file = tempnam(sys_get_temp_dir(), 'ftp_download');
$remote_file = $path . "/" . $file;
// Download the file from FTP server to local file
if (!ftp_get($this->conn_id, $local_file, $remote_file, FTP_BINARY))
{
echo json_encode([
"status" => "error",
"message" => "Failed to download '" . $remote_file . "'"
]);
exit();
}
// Create a unique download URL for the file
$download_url = url('download.php?file=' . urlencode($local_file) . '&name=' . urlencode($file));
// Close the FTP connection
ftp_close($this->conn_id);
echo json_encode([
"status" => "success",
"message" => "File has been downloaded.",
"download_url" => $download_url
]);
exit();
}
It will also return the “download_url” variable. That will be link to file from where you can download the file.
Download from server to local computer
Create a new file named “download.php” in your server and write the following code in it:
if (isset($_GET['file']) && isset($_GET['name']))
{
$temp_file = $_GET['file'];
$file_name = $_GET['name'];
if (file_exists($temp_file))
{
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="' . $file_name . '"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($temp_file));
// Read the file and output it to the browser
readfile($temp_file);
// Delete the temporary file
unlink($temp_file);
exit();
}
echo "File does not exist.";
exit();
}
echo "Invalid request.";
exit();
9. Rename file
Renaming the file on FTP using PHP is very easy. You just have to provide 3 things:
Folder name
Old file name
New file name
public function rename()
{
$this->do_connect();
$path = "/directory-name";
$name = "new-file-name.php";
$file = "old-file-name.php";
// File to be renamed on the FTP server
$remote_file = $path . "/" . $file;
$remote_new_file = $path . "/" . $name;
// Try to rename the file or folder
if (!ftp_rename($this->conn_id, $remote_file, $remote_new_file))
{
echo json_encode([
"status" => "error",
"message" => "There was a problem renaming " . $file . " to " . $name
]);
exit();
}
echo json_encode([
"status" => "success",
"message" => "Successfully renamed " . $file . " to " . $name
]);
exit();
}
10. Delete file
Deleting a file from FTP in PHP is very simply. You just need to enter the full path of the file and call the PHP built-in ftp_delete function. Pass the FTP connection ID and file path as arguments.
public function delete_file()
{
$this->do_connect();
$path = "/directory-name/file-name.php";
// Delete the file on the FTP server
if (!ftp_delete($this->conn_id, $path))
{
echo json_encode([
"status" => "error",
"message" => "There was a problem while deleting " . $path
]);
exit();
}
echo json_encode([
"status" => "success",
"message" => "Successfully deleted " . $path
]);
exit();
}
11. Delete folder
Deleting a folder is NOT as simple as deleting a single file. There are 2 steps involved in deleting a folder from FTP in PHP.
Recursively delete all files and folders inside that folder.
Delete the folder itself.
So first we will create a function that will initialize the call to recursive function.
public function delete_folder()
{
// Set maximum execution time to unlimited (0 means no limit)
set_time_limit(0);
$path = "/directory-path/folder-name";
$this->do_connect();
$this->ftp_delete_dir($path);
echo json_encode([
"status" => "success",
"message" => "Folder has been deleted."
]);
exit();
}
Our recursive function ftp_delete_dir will look like this:
// Function to recursively delete a directory
private function ftp_delete_dir($path)
{
// Get the list of files in the directory
$files = ftp_nlist($this->conn_id, $path);
// Loop through each file
foreach ($files as $file)
{
$file = basename($file);
if ($file == '.' || $file == '..')
{
continue;
}
$file_path = "$path/$file";
// If it's a directory, delete recursively
if (@ftp_chdir($this->conn_id, $file_path))
{
ftp_chdir($this->conn_id, '..');
ftpDelete($this->conn_id, $file_path);
}
else
{
// If it's a file, delete it
ftp_delete($this->conn_id, $file_path);
}
}
// Finally, remove the directory itself
ftp_rmdir($this->conn_id, $path);
}
It does the following things:
Loops through all the files inside that folder.
Skip the “.” and “..” folders (they are just pointing towards current and parent directory respectively).
If the file is a directory, start the recursion.
Else delete the file.
Finally at line #33, we are deleting the current directory itself.
So these are all the features we have in FTP manager I created in PHP and MySQL using Laravel framework. If you have any quetions regarding FTP or if you are having any problem, feel free to contact me.
A file manager web app is created in Laravel and React JS. We offer free 10 MB storage so you can test this script. Test it before you buy it. Easy deployment, you can just buy and upload the files on your server. Further instructions for deployment are in the file “README.md”. Check our tutorial if you need help in deployment.
We are using CloudBox Lite HTML template for this project.
I am using Laravel Sanctum API for handling authentication. It creates a token for each user and sends it in headers in AJAX requests. It is also useful so if you want to develop a mobile application for it, you can use the same authentication system. Because session authentication does not work on mobile.
2) Files and Folders
User can create as much folders as he wants and he can upload as much files as he wants unless his storage gets full. There is unlimited level of folder nesting just like in your computers, you can create folders and create folders inside it.
3) Rename
You can rename files and folders any time you want. You can also set the same name of different files in the same folder.
4) Private or public files
While uploading files, you can set if the file is publicly visible to other users. Or will it be only for you. You can share publicly available files with others.
User can change from public to private any time. Public files are saved in storage so they can be accessed by other users. While private files are saved in database in BLOB format. So they can only be accessible by the user who uploaded it.
5) Trash can
If you delete the file or folder by accident, it won’t be deleted permanently. It will be moved to trash where it remains unless you delete it. From trash can delete the file permanently or you can restore it. If you restore it, it will go to the same folder where it was before.
6) Share files
You can share files with other users as well if the file is public. While sharing file you can also set if the other user can just read it, or if he can modify the content of the file. Only text and source code file’s (txt, php, html, css, js, java, c, cpp, py, go, sql) content can be modified.
7) Realtime Collaboration
User can allow other’s to change the content of file without having to refresh the page. File owner can give write permission to a user and he will be able to edit the file. This is very useful for teams. Programmers can use this feature to work on the same project.
Making collaboration realtime using Node JS – File manager in Laravel and React JS
8) Profile
User can manage his personal information from his profile page. He can edit his name, phone and profile image. When user uploads a new profile image, we delete his old profile image. So only 1 image of user is saved in file system. The profile image is displayed when he shares a file with someone and also when someone adds him in his contact list.
9) Change Password
User can change his password. For that, he needs to enter his current password first. This is to prevent any other person to change his password. Passwords are stored using password_hash() PHP function that generates a store hash. It is a one-way hash, which means that once hashed, it cannot convert back to plain text. So even if someone sees your database, he won’t be able to tell the user’s passwords.
10) Email Settings
Now user can control when he wants to receive an email. Right now we are giving him 2 options:
When someone add me in his contact list.
When someone shares a file with me.
11) Contact List
If there are some people with whom you have files frequently. Then you do not need to type their email address everytime you share the file with them. Just add them in your contact list and next time you try to share a file with them, you will see a dropdown list with all your contacts. You can just pick the contact and hit “Share” button.
You can also see all the files you have shared with specific person from contact list.
The error you are having is because the double curly braces {{ which are used in React JS for styling the tag, are also used by Laravel blade template to render the value of a PHP variable. Laravel will think of it as a PHP variable and will throw an error.
To fix this error, you need to create a separate object in your React JS component. That object will have all the styles for each tag. Modify your React JS component to the following:
You can see that instead of setting the CSS directly in the style attribute, I have created a separate variable and used its value as a variable. This way your error gets fixed. Also, it will help you in setting CSS styles to multiple tags without duplicating them.