A Video Tutorial on Server Side Rendering, which describes how exactly client side rendering happens, what are the benefits on Server Side Rendering.
Category: Uncategorized
COVID-19 : corona virus epidemic, What one can do to stop it?
The world has hit badly by an invisible tiny virus who is shaking the entire scientific, medical community and challenging to save the lives. Corona virus is not that critical if every one takes some simple precautions but as usual we did mistakes, we neglected and hence paying for it and struggling to escape from it.
![](https://akm-img-a-in.tosshub.com/sites/btmt/images/stories/coronavirus2_660_280320122341.jpg)
Coronavirus is spreading very fast, its an exponential way, person to person through different medium and hence an extreme precautions has to be taken to stop it
Social Distancing:
A simple technique can save our life and save your family, social distancing. Virus can spread through person to person when a infected person cough, spit, sneezes.
It will also spread through some surfaces when an infected person touch any metal surface, cardboard, plastic the virus can survive several hours on the surface and some one else touch the same surface it will transfer to his body.
Look at the below animated view which helps us to understand how social distancing helps us to stop coronavirus spread drastically
Is’t it a simple solution ? but we are failing follow.
![](https://thespinoff.co.nz/wp-content/uploads/2020/03/Covid-19-Transmission-graphic-01.gif)
“By our most conservative estimate, at least 59% of the infected individuals were out and about, without being tested and potentially infecting others,” says lead study author Prof. Wu Tangchun. Reference
What you should not do ?
Avoid
- Parties, functions
- Smoking
- Avoid taking tablets on your own for fever , cold or headache.
- touching your eyes, nose and mouth without washing it properly with soap and water or sanitisers
Social Warriors and NGOs working for Covid-19
There are lot of NGOs, social warriors working for coronavirus epidemic to stop it, lot of awareness programs running for COVID-19, lot of donations are being raised by many organisations to help the needy people in this lockdown situation almost everywhere in the world
Awareness Programs Run by SociallyGood Platform through some of the organisations
Awareness Campaign For Pandemic COVID-19
Awareness program by Sewa USA :
Coronavirus-(COVID-19) Awareness Program
Donate for Covid-19 epidemic
Donation Campaigns run by SociallyGood Platform through some of the organisations
Groceries to daily wage workers in view of outbreak of COVID-19
know more about COVID-19 through SociallyGood Platform
COVID-19 Campaigns on SociallyGood Platform
![](https://knowledge-cess.com/wp-content/uploads/2020/04/SociallyGood-Campaigns-on-COVID-19-1024x500.jpg)
Let us stop Coronavirus by following the protocol
- Lockdown : Be at home, do not go out without the real need
- Social Distancing: Keep distance between people
- Be wise not panic
- Improve your health by doing simple physical work like yoga
COVID-19 Information Center on Facebook
Amazon AWS RDS Failed to Connect to MySQL at with user using MySql Workbench
When trying to connect to Amazon AWS RDS from local machine using MySql Workbench , if you face connection issue like error: Failed to Connect to MySQL at with user Kindly follow below steps
Follow setting up security group : Refer
Then set public access try by following these steps
To change the Publicly Accessible property of the Amazon RDS instance to Yes:
1. Verify that your VPC has an internet gateway attached to it and that the inbound rules for the security group allow connections.
2. Open the Amazon RDS console.
3. Choose Databases from the navigation pane, and then select the DB instance.
4. Choose Modify.
5. Under Network & Security, choose Yes for Public accessibility.
6. Choose Continue.
7. Choose Modify DB Instance.
DB Import Error due to Triggers :
ERROR 1419 (HY000) at line 918: You do not have the SUPER privilege and binary logging is enabled (you might want to use the less safe log_bin_trust_function_creators variable)
To fix this issue follow steps
- Open the RDS web console.
- Open the “Parameter Groups” tab.
- Create a new Parameter Group. On the dialog, select the MySQL family compatible to your MySQL database version, give it a name and confirm. Select the just created Parameter Group and issue “Edit Parameters”.
- Look for the parameter ‘log_bin_trust_function_creators’ and set its value to ’1′.
- Save the changes.
- Open the “Instances” tab. Expand your MySQL instance and issue the “Instance Action” named “Modify”.
- Select the just created Parameter Group and enable “Apply Immediately”
- Click on “Continue” and confirm the changes.
- Wait for the “Modifying” operation to be completed.
- Again, open the “Instances” tab. Expand your MySQL instance and
- expand “Instance Action” tab and select “Reboot”.
Factory Design Pattern : A Creational Design Pattern
Factory design patterns provides an interface to create an object. Object creation is not just allocating some memory, in a complex systems the object creation will be a complex process. Setting certain defaults, following certain steps and initialisation of an object many more aspects will be taken care.
Let us take an example to understand it better, when we handle payment gateway transactions, a transaction object is not a simple object, it has much more complexities. It may be handling specific details for Master cards, Visa cards, or it may be related to income tax etc.
There are multiple ways of handling factory design patter, Factory Method pattern and Abstract Factory class are two different approaches.
![](https://knowledge-cess.com/wp-content/uploads/2020/01/FactoryMethood.png)
Factory Method Pattern
Without a design pattern the code looks as fallow
processPayment() {
switch(paymentGateway) {
case 'RazorPay':
transaction = new RazorPayTransaction();
break;
case 'Paypal':
transaction = new PaypalTransaction();
break;
case 'Paypal':
transaction = new StripeTransaction();
break;
}
}
However the above code looks more cleaner when we apply design pattern the code looks as fallow
createRazorPayTransaction() {
transaction = new RazorPayTransaction();
return transaction;
}
createPaypalTransaction() {
transaction = new PaypalTransaction();
return transaction;
}
createTransactionFactory(paymentGateway) {
switch(paymentGateway) {
case 'RazorPay':
createRazorPayTransaction();
break;
case 'Paypal':
createPaypalTransaction();
break;
case 'Paypal':
break;
}
}
processPayment() {
transaction = createTransactionFactory('RazorPay');
}
the above code looks simple and we may not understand the significance of it with a small scale application. However the creational design pattern brings in lot of flexibility, like any complexity with respect to a particular payment gateway will be handled with respective creation method.
for example if I try to elaborate little about one particular method it may looks as below, and this shows how a particular method becomes complex while considering various cases.
createPaypalTransaction() {
transaction = new PaypalTransaction();
if (cardType === 'Master') {
if (country === 'India') {
if (cardKind === 'Chip') {
}
}
}
return transaction;
}
Abstract Factory Pattern
Abstract factory pattern simplifies and makes the pattern into more object oriented and enforces future extendability to follow certain strict guidelines by defining interfaces.
Taking an example of developing a super software to handle a robotic machines. There are various types of robotic machines like marine explorer, space explorer and terrain explorer. Its great to have abstract class which enforces and defines basic structure of the factory class. Let us see how does it look
![](https://knowledge-cess.com/wp-content/uploads/2020/01/Abstract-Factory-Pattern-1024x650.jpg)
abstract class RoboticMachineFactory {
createCrawlingRobot();
createRunningRobot();
createFlyingRobot();
}
class SpaceExplorerRobotFactory extends RoboticMachineFactory {
createCrawlingRobot();
createRunningRobot();
createFlyingRobot();
}
class TerrainExplorerRobotFactory extends RoboticMachineFactory {
createCrawlingRobot();
createRunningRobot();
createFlyingRobot();
}
class MarineExplorerRobotFactory extends RoboticMachineFactory {
createCrawlingRobot();
}
Classification of design patterns : Creational Design Patterns
Before reading further , let us first understand what are design patterns read part 1 of this article
Creational Design Pattern
Object creation is a very common pattern we need to use almost for all complex objects. Object creation is not just allocating a memory and use it, we may need to consider lot of aspects while creating an object.
Creational design pattern solves this problem by following a sophisticated approach, typically creational design patterns will be used for initialising hardware configuration, database connections , Logger object.
Creational design patterns are important to use because they follow SOLID Principles closely. It allows long term flexibility, it allows more decoupling and easily testable.
Let us look into some of the important creational design patterns
Singleton Pattern
We have to identify a scenario where we may need to maintain only one object, even if you try to create an object, the program should not allow to create new object instead it has to return only one object.
Singleton pattern is meaningful where multiple objects doesn’t make any sense. Taking few scenarios here for example , DBConnectionHandler, MQManager for managing Queue connections, these are classical examples where having multiple objects has no meaning.
Example of Singleton Pattern in Javascript
class MQManager {
constructor() {
this.amqpProducerConn = null;
this.amqpConsumerConn = null;
this.producerChannel = null;
this.consumerChannel = null;
}
createProducerConnection(onConnectSuccess, onConnectFail) {
}
createConsumerConnection(onConnectSuccess, onConnectFail) {
}
createProducerChannel(connection) {}
createConsumerChannel() {}
enqueueJob(queueName, jobDetails) {}
dequeueJob(queueName, consumerCallback) {}
closeProducerConnectionOnErr(err) {}
closeConsumerConnectionOnErr(err) {}
};
module.exports = (() => {
let instance;
function getInstance() {
//TO RESTRICT CREATING SINGLE OBJECT
if (instance === undefined) {
instance = new MQManager();
}
return instance;
}
// Public API definition
return {
getInstance
};
})();
The above class we can import as follows
const MQManager = require('./mqManager').getInstance();
Read More About Creational Design Pattern
Thanks to refactoring.guru for wonderful images- https://refactoring.guru/design-patterns/
Design Patterns – importance and Examples
What are design pattern?
![](https://knowledge-cess.com/wp-content/uploads/2019/12/problem_png_1113337-1.png)
design patterns are typical solutions to common problems a developer face repeatedly
Design Patterns Classification
Creational Pattern
These patterns provides various objects creation mechanism. Which increase flexibility and reuse of existing code
![](https://knowledge-cess.com/wp-content/uploads/2019/12/factory-method-2x-1024x640.png)
Structural Pattern
These patterns explain how to assemble objects and classes into larger structure, while keeping these structures flexible and efficient
![](https://knowledge-cess.com/wp-content/uploads/2019/12/adapter-mini-2x.png)
Behavioral Pattern
These patterns are concerned with algorithms and assignment or responsibilities between objects
![](https://knowledge-cess.com/wp-content/uploads/2019/12/chain-of-responsibility-mini-2x.png)
Design patterns are the best practices adapted by experienced software developers, with a vast experience, we developers will find a best way to solve a problem which we face almost every day. The outcome of such solution we usually call it as design patterns
Let us look into some of the design patterns: Read Here
Thanks to refactoring.guru for wonderful images- https://refactoring.guru/design-patterns/
Server Side Rendering (SSR) in React 16 with create-react-app using Material Ui, Redux and Express Libraries
What is Server Side Rendering in React (SSR)?
Server side rendering is normally rendering the requested page at server side of client and sending back the whole html page from server.
i.e: Server-side rendering is all about handling the initial render whenever a request hits the server. For more on basics of SSR please read my first article
Let us see how to implement server side rendering in ReactJs
How to Enable Server Side Rendering using React and ExpressJS
Dependencies:
React: 16.7.0
Material Ui Library from Google: v3.9.3
redux: 4.0.1
redux-thunk: 4.0.1
express: 4.17.1
react-jss: 8.6.1
react-router-dom: 4.3.1
react-document-meta: 2.1.2
axios: 0.19.0
@babel/plugin-proposal-class-properties: 7.4.0
@babel/preset-env: 7.4.3
@babel/register: 7.4.4
babel-preset-es2015: 6.24.1
Step1: Create React Application
Create a react app using command create-react-app
Install the create-react-app globally on your machine with below command.
React: 16.7.0
Material Ui Library from Google: v3.9.3
redux: 4.0.1
redux-thunk: 4.0.1
express: 4.17.1
react-jss: 8.6.1
react-router-dom: 4.3.1
react-document-meta: 2.1.2
axios: 0.19.0
@babel/plugin-proposal-class-properties: 7.4.0
@babel/preset-env: 7.4.3
@babel/register: 7.4.4
babel-preset-es2015: 6.24.1
npm install -g create-react-app
Create a project by create-react-app as follows
create-react-app ssr-react-16
Step2: Install necessary npm packages for React server side rendering applicationInstall the following packages by running the following commands, if necessary please use the same version too.
npm install @material-ui/core npm install react-redux npm install redux npm install redux-thunk npm install express npm install react-router-dom npm install react-document-meta npm install react-jss npm install axios npm install @babel/plugin-proposal-class-properties npm install @babel/preset-env npm install @babel/register npm install babel-preset-es2015
Thats it now your app is ready with library setup
Step3: babel configs for react server side app
Create a file called .babelrc in root directory of the app and paste the below code.
Babel is a toolchain that is mainly used to convert ECMAScript 2015+ code into a backwards compatible version of JavaScript in current and older browsers or environments. For more you can read the babel doc.
{ "presets": ["@babel/env", "@babel/preset-react"], "plugins": [ "@babel/plugin-proposal-class-properties" ] }
Step4:
Create a file called www under bin folder which is in root directory
In this file we will be creating a server for client and allocate a port (I am using 5000 here)
Copy the code below to file just created
const app = require('../src/client/src/ssr/clientServer'); const http = require('http'); const port = normalizePort(process.env.PORT || 5000); app.set('port', port); const server = http.createServer(app); server.listen(port); function normalizePort(val) { const port = parseInt(val, 10); if (isNaN(port)) { // named pipe return val; } if (port >= 0) { // port number return port; } return false; }
In the above code snippet, we are importing a file called clientServer.js that’s covered in the next step.
Step5: ReactJS server side script to initialise server part of client app.
Create a file clientServer.js
For better folder structure, I have organised as shown in the below screenshot where bin and src will falls under root directory. Paste the below code in clientServer file. clientServer is kind of server side script for our client application, it will initiate expressjs and configurations for server side script of client.![](https://knowledge-cess.com/wp-content/uploads/2019/08/ssr-react-16-api-folder-structure-351x1024.png)
require("@babel/register")({ presets: ["@babel/preset-env"] }); const express = require('express'); const path = require('path'); const requestHandler = require('./requestHandler'); const app = express(); //static files nd build file reference app.use(express.static(path.join(__dirname, '../../../../build'))); app.use(express.static(path.join(__dirname, 'public'))); app.set('view engine', 'ejs'); app.set('views', path.join(__dirname, 'public')); //for server side rendering app.use(requestHandler); // catch 404 and forward to error handler app.use((req, res, next) => { const err = new Error('Notdff Found'); err.status = 404; next(err); }); module.exports = app;
In the above code you can see a requestHandler file, which is very important file and will see there.
Step6: A request handler for ReactJS for server side rendering and invoking (calling) apis at server side
This step is very important for serving the requested page from server side. All magic of serving the requested page is done in this script. When client request for a page, it matches the path and determines whether is there any API call for this page and invokes api then updates HTML body for the respective response. Basically here its creating the react component at server side. Hence React component is fully ready with all the data for the first render itself. If there is no api call for a particular page, it just serves a just a static page
Create a file requestHandler.js Copy the below code.
'use strict'; import React from 'react'; import { Provider } from 'react-redux'; import thunk from 'redux-thunk'; import { applyMiddleware, createStore } from 'redux'; import { renderToString } from 'react-dom/server'; import { SheetsRegistry } from 'jss'; import JssProvider from 'react-jss/lib/JssProvider'; import path from 'path' import fs from 'fs' import { MuiThemeProvider, createMuiTheme, createGenerateClassName, } from '@material-ui/core/styles'; import green from '@material-ui/core/colors/green'; import red from '@material-ui/core/colors/red'; import { StaticRouter, matchPath } from 'react-router-dom'; import DocumentMeta from 'react-document-meta'; import reducers from '../reducers/index'; import routes from '../routes'; import routesConfigs from './routesConfig'; const middleware = applyMiddleware(thunk); function renderView(req, res, state) { // Create a theme instance. const theme = createMuiTheme({ palette: { primary: green, accent: red, type: 'light', }, }); // STEP-1 CREATE A REDUX STORE ON THE SERVER const store = createStore(reducers, state, middleware); const sheetsRegistry = new SheetsRegistry(); // Create a sheetsManager instance. const sheetsManager = new Map(); const generateClassName = createGenerateClassName(); // STEP-2 GET INITIAL STATE FROM THE STORE const initialState = JSON.stringify(store.getState()).replace(/<\/script/g, '<\\/script').replace(/<!--/g, '<\\!--'); // STEP-3 IMPLEMENT REACT-ROUTER ON THE SERVER TO INTERCEPT CLIENT REQUESTs AND DEFINE WHAT TO DO WITH THEM const context = {}; const reactComponent = renderToString( <JssProvider registry={sheetsRegistry} generateClassName={generateClassName}> <MuiThemeProvider theme={theme} sheetsManager={sheetsManager}> <Provider store={store}> <StaticRouter location={req.url} context={context}> {routes} </StaticRouter> </Provider> </MuiThemeProvider> </JssProvider> ); const css = sheetsRegistry.toString() const reactMetaComponent = DocumentMeta.renderToStaticMarkup(); if (context.url) { // can use the `context.status` that // we added in RedirectWithStatus redirect(context.status, context.url); } else { //https://crypt.codemancers.com/posts/2016-09-16-react-server-side-rendering/ //res.status(200).render('index', { reactComponent, reactMetaComponent, initialState }); fs.readFile(path.resolve('build/index.html'), 'utf8', (err, data) => { if (err) { return res.status(500).send('An error occurred') } const replacedData = data.replace( '<div id="root"></div>', `<div id="root">${reactComponent}</div> <style id="jss-server-side">${css}</style> <script> window.INITIAL_STATE = ${initialState} </script>` ); const replacedMetaTagData = replacedData .replace(`<meta id="reactMetaTags"/>`, `${reactMetaComponent}`); res.send(replacedMetaTagData); }) } } function handleRender(req, res) { const components = routesConfigs .filter(route => matchPath(req.path, route)) // filter matching paths .map(route => route.component); // check if components have data requirement let promiseObj = null; if (components.length > 0 && (components[0].fetchData instanceof Function)) { /* fetchData is the function defined in each component and make it like class function and it will be called at server side */ components[0] .fetchData(req.query) .then((response) => { renderView(req, res, response); }) .catch((error) => { console.log('***--- handleRender error ', error); renderView(req, res, {}); }); } else { renderView(req, res, {}); } } module.exports = handleRender;
- By default it will be executing a handleRender function in the above code. In the handleRender function, we read a routesConfig file which is just for keeping track of respective component for each route path.
import LandingComponent from '../pages/landing/components/LandingComponent'; import AboutComponent from '../pages/about/components/AboutComponent'; export default [ { path: "/", component: LandingComponent, exact: true, }, { path: '/about', component: AboutComponent, exact: true, } ];
- routesConfigs will be used by requestHandler to find dynamically which component needs to be rendered for the request. It also checks for fetchData, if fetchData is defined by the component then requestHandler will invoke it which internally invokes api. Note here is all this is happening at server side not on the browser, component object is created in server and fetchData action will be invoked in server. You can see the brief description of fetchData and how to use this in the component in the next step.
- When renderView is called, every times it creates is own redux store and a material ui theme provider, thats why we follow this code(which is also mention in the above code snip).
const theme = createMuiTheme({ palette: { primary: green, accent: red, type: 'light', }, }); // STEP-1 CREATE A REDUX STORE ON THE SERVER const store = createStore(reducers, state, middleware); const sheetsRegistry = new SheetsRegistry(); // Create a sheetsManager instance. const sheetsManager = new Map(); const generateClassName = createGenerateClassName();
- Next major step is reading a build/index.html file which you will get by running npm run build,
Here we will be injecting the component created at server side into index.html.const replacedData = data.replace( '<div id="root"></div>', `<div id="root">${reactComponent}</div> <style id="jss-server-side">${css}</style> <script> window.INITIAL_STATE = ${initialState} </script>` );
where in index.html of public folder should compulsory has this tag
<div id="root"></div>
- For facebook sharing, when you share the url a image and the title and description of the page has to be displayed, for that all those content has to be in the meta tag inside the head tag, hence we need to replaced meta tag with server generated meta tag code.
const replacedMetaTagData = replacedData .replace(`<meta id="reactMetaTags"/>`, `${reactMetaComponent}`);
Where in index.html of public folder, meta tag with id is should be unchanged
<meta id="reactMetaTags"/>
- Finally we will serve the requested page with updated meta tags and updated html for the first rendering cycle it self.
res.send(replacedMetaTagData);
Step 7
- Every component should define an action which will be invoked from server side script, however in server side the request handler will be a generic script and we have to dynamically invoke an action at server side, to achieve that, each component has to define an action and assign action function pointer to fetchData, fetchData is a static class variable kept in component. Check the below code snippet , fetchData is defined at AboutComponent class level and a pointer to action is assigned to it.
AboutComponent.fetchData = fetchAboutData; export default connect(mapStateToProps, null)(AboutComponent);
- You can refer to the fetchAboutData action in the aboutActions.js which will make the API call to some server, for testing iI am using the JSON placeholder get API which will get the list of posts as response, refer the code below
import axios from 'axios'; export const fetchAboutData = (params) => { return new Promise((resolve, reject) => { const url = 'https://jsonplaceholder.typicode.com/posts'; axios .get(url) .then(response => { resolve({ about: { posts: response.data } }); }) .catch((error) => { console.log('Error while fetching posts from network', error); reject(null); }); }); }
- In the positive view, it goes to then block(success block) of the axios api call, you can observe that it’s not direct resolve, its resolving a reducer named about and that contain the posts as one of the key, this set up has to be same in both client side reducer as well in axios call in order to use it component (About Component), Observe the below codes, I have shown the code snips of axios call, aboutReducer to mapStateToProps in AboutComponent,
In axios callresolve({ about: { posts: response.data } });
In about reducer
const INITIAL_STATE = { posts: [] };
In about component
const mapStateToProps = (state) => { return { posts:state.about.posts }; }
- So in the render method, you can access the posts array like this.props.posts, in the return method of render function i have written one more function which will return the list of posts(only title) and it creates a html code
getAllPosts = () => { const postView = this.props.posts.map(post => <li>{post.title}</li> ); return postView; }
- Once the html is ready, then its in the success block of the fetchData function in the handleRender function of requestHandler file , then followed by the code it calls the renderView method along with data(html) returned from the component.
Step8 :
Update the package.json start script to point to server side rendering beginning of the file, thats www under bin directory. Now server side rendering is really ready.
"scripts": { "start": "node bin.www",
Step9 : Running project:
- In the requestHandler file we will be pointing to index.html inside the build folder, hence we need to generate a build from react by running the command
npm run build
- Run the start command of your script by
npm run start
OR
nodemon
OR
node bin/www
- Since we are running this project on 5000 port, run http://localhost:5000 which is just a page without requesting for API, you simply see as like below
- I have made one more component with calling API and printing the results on screen, run http://localhost:5000/about . I am using an open dummy api for printing list of posts,
Ie: https://jsonplaceholder.typicode.com/posts
The output picture is shown below
For View Tutorial on Server Side Rendering using ReactJS, Material-ui and Redux with explanation of each code snippet click here
An Example Source Code is in Github project Link : https://github.com/pilleanand/ssr-react16/tree/master/ssr-react-16
Common issues faced in React SSR Applications
Posted by:
Anand S,
Software Engineer, Soczen Technologies Pvt Ltd,
Developer: https://sociallygood.com
React Native Android Exception : App Crashes on Launch
How to check exception ? On crash it just shows Close app dialogue box. To check what is the crash open adb logs and check.
<User_home_directory>/Library/android/sdk/platform-tools/adb logcat
This command shows below exception
Exception : java.lang.RuntimeException: Unable to start activity ComponentInfo{/.MainActivity}: java.lang.IllegalStateException: Only fullscreen opaque activities can request orientation
Fix For this :
Remove android:screenOrientation from your application manifest xml
ReactNative Firebase Application : Firebase App named ‘[DEFAULT]’ already exists (app/duplicate-app)
If by change you are getting following exception
Firebase App named ‘[DEFAULT]’ already exists (app/duplicate-app)
Then do the following fix :
Check whether firebase is already initialised or not before calling firebase.initializeApp
if (!firebase.apps.length) { firebase.initializeApp(firebaseConfig); }
How to Increase Upload Speed for GoogleCloudStorage in nodejs
How to Increase Upload Speed for GoogleCloudStorage in nodejs
Uploading Files to GCP : Google Cloud Storage In Nodejs
const Storage = require('@google-cloud/storage'); const config = require('./gcloudConfig'); const Multer = require('multer'); const CLOUD_BUCKET = config.get('CLOUD_BUCKET'); const storage = Storage({ projectId: config.get('GCLOUD_PROJECT') }); const bucket = storage.bucket(CLOUD_BUCKET); // Returns the public, anonymously accessable URL to a given Cloud Storage // object. // The object's ACL has to be set to public read. // [START public_url] function getPublicUrl (filename) { return `https://storage.googleapis.com/${CLOUD_BUCKET}/${filename}`; } // Express middleware that will automatically pass uploads to Cloud Storage. // req.file is processed and will have two new properties: // * ``cloudStorageObject`` the object name in cloud storage. // * ``cloudStoragePublicUrl`` the public url to the object. // [START process] function sendUploadToGCS (req, res, next) { if (!req.files) { return next(); } const data = req.body; if (req.files.length === 0) { next(); } data.accountNumber = ''; for (let index = 0; index < req.files.length; index++) { const gcsname = `${data.accountNumber}/${Date.now()}${req.files[index].originalname}`; const file = bucket.file(gcsname); const stream = file.createWriteStream({ metadata: { contentType: req.files[index].mimetype }, resumable: false }); stream.on('error', (err) => { req.files[index].cloudStorageError = err; next(err); }); // console.log(' upload in progress for file ', index); stream.on('finish', () => { req.files[index].cloudStorageObject = gcsname; file.makePublic().then(() => { req.files[index].cloudStoragePublicUrl = getPublicUrl(gcsname); console.log(' upload completed, public url is ', req.files[index].cloudStoragePublicUrl, ' index ', index, ' total count ', req.files.length); if (index === (req.files.length - 1)) { next(); } }); }); stream.end(req.files[index].buffer); } } // [END process] // Multer handles parsing multipart/form-data requests. // This instance is configured to store images in memory. // This makes it straightforward to upload to Cloud Storage. // [START multer] const multer = Multer({ storage: Multer.MemoryStorage, limits: { fileSize: 5 * 1024 * 1024 // no larger than 5mb } }); // [END multer] module.exports = { getPublicUrl, sendUploadToGCS, multer };
The issue is the upload speed is very slow, finding a way to upload faster to google cloud storage