Can't stream video from MongoDB using GridFS - node.js

I am trying for quite some time to stream a video from MongoDB. Read tons of api DOCs and examples just can't get it to work
This is my front-end video Handler :
import { useState, useEffect } from "react";
import ReactPlayer from "react-player";
const CatVideos = () => {
const [videoList, setvideoList] = useState(null);
useEffect(() => {
const getVideos=async ()=> {
const response = await fetch('http://localhost:8000/cat-videos/videos');
const data = await response.json();
setvideoList(data);
console.log(data);
}
getVideos();
}, [])
return (
<div>
<h1>Cat videos</h1>
{videoList!=null && videoList.map((video)=>{
return <ReactPlayer key={video._id} url={'http://localhost:8000/cat-videos/videos/'+video._id}/>
})}
</div>
);
};
export default CatVideos;
Backend stream function :
exports.getVideoStream = (req, res, next) => {
var id = req.params.id;
let gfs = Grid(conn.db, mongoose.mongo);
gfs.collection("videos");
gfs.files
.findOne({
_id: mongoose.Types.ObjectId(id),
})
.then((result) => {
const file = result;
if (!file) {
return res.status(404).send({
err: "Unavailable.",
});
}
if (req.headers["range"]) {
var parts = req.headers["range"].replace(/bytes=/, "").split("-");
var partialstart = parts[0];
var partialend = parts[1];
var start = parseInt(partialstart, 10);
var end = partialend ? parseInt(partialend, 10) : file.length - 1;
var chunksize = end - start + 1;
res.header("Accept-Ranges", "bytes");
res.header("Content-Length", chunksize);
res.header(
"Content-Range",
"bytes " + start + "-" + end + "/" + result.length
);
console.log(result.contentType)
res.header("Content-Type", result.contentType);
gfs.createReadStream({
_id: result._id,
range: {
startPos: start,
endPos: end,
},
}).readStream.pipe(res);
} else {
console.log("#################before####################");
res.header("Content-Length", result.length);
res.header("Content-Type", result.contentType);
console.log(result._id);
gfs
.createReadStream({
_id: result._id,
})
.pipe(res);
}
})
.catch((err) => {
res.json(err);
});
};
I do get a response from this function , and it appears that the "Content-Type" remains unchanged.
HTTP/1.1 206 Partial Content
X-Powered-By: Express
Access-Control-Allow-Origin: *
Accept-Ranges: bytes
Date: Thu, 23 Dec 2021 19:38:25 GMT
Content-Type: application/json; charset=utf-8
ETag: W/"2-vyGp6PvFo4RvsFtPoIWeCReyIC8"
Content-Range: bytes 0-1/2
Content-Length: 2
Backend dependencies:
"dependencies": {
"bcryptjs": "^2.4.3",
"body-parser": "^1.19.1",
"cors": "^2.8.5",
"ejs": "^3.1.6",
"express": "^4.17.2",
"gridfs-stream": "^1.1.1",
"method-override": "^3.0.0",
"mongodb": "^4.2.2",
"mongoose": "^6.1.2",
"multer": "^1.4.4",
"multer-gridfs-storage": "^5.0.2"
}
Frontend dependencies:
"axios": "^0.24.0",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-player": "^2.9.0",
"react-router-dom": "^6.2.1",
"react-scripts": "4.0.3",
"web-vitals": "^1.1.2"

I managed to fix the issue. Note that GridFSBucket has a default bucket name.
Going over the API docs it says it appends the bucket name ".files".
My issues were that I did not define it and start end inside download stream were not defined correctly causing an error.
You may use it as well to stream Images,videos just change the content type on the frontend. Pretty generic stream.
exports.getVideoStream = (req, res, next) => {
mongodb.MongoClient.connect(url, function (error, client) {
if (error) {
res.status(500).json(error);
return;
}
// Check for range headers to find our start time
const range = req.headers.range;
if (!range) {
res.status(400).send("Requires Range header");
}
const db = client.db('videos');
// GridFS Collection
console.log(req.params.id);
db.collection('videos.files').findOne({_id:mongoose.Types.ObjectId(req.params.id)}, (err, video) => {
if (!video) {
res.status(404).send("No video uploaded!");
return;
}
// Create response headers
const videoSize = video.length;
const start = Number(range.replace(/\D/g, ""));
const end = videoSize - 1;
const contentLength = end - start + 1;
const headers = {
"Content-Range": `bytes ${start}-${end}/${videoSize}`,
"Accept-Ranges": "bytes",
"Content-Length": contentLength,
"Content-Type": "video/mp4",
};
// HTTP Status 206 for Partial Content
res.writeHead(206, headers);
// Get the bucket and download stream from GridFS
const bucket = new mongodb.GridFSBucket(db,{bucketName:"videos"});
const downloadStream = bucket.openDownloadStream(video._id, {
start:start,
end:end
});
// Finally pipe video to response
console.log(streamCounter," start ",start," end ",end)
streamCounter++;
downloadStream.pipe(res);
});
});
};

Related

Why Browser gets round trip/refreshed after uploading image more than 9 MB in reactjs?

I have a ReactJS APP. The logic in the APP needs to make an http post request to nodejs uploading image api,
capturing the response from api give some errors and sometimes uploads, and then refreshed the browser instantly. My problem is capturing the http response from nodejs api asynchronously and returning it to the image/display list without a browser refresh.
When I try to upload more than 6MB to 46MB then a browser refresh must be occured.
--- ImageComponent.js
function EditImageSlider({ breadcrumb, pageName, setLoader, showToast }) {
const history = useHistory();
const list = useSelector((state) => state.imagecrop.list);
const detail = useSelector((state) => state.imagecrop.detail);
const row = useSelector((state) => state.imagecrop.row);
const imageCropWidth = useSelector((state) => state.imagecrop.imageCropWidth);
const imageCropHeight = useSelector((state) => state.imagecrop.imageCropHeight);
const croppedImage = useSelector((state) => state.imagecrop.croppedImage);
const Image = useSelector((state) => state.imagecrop.Image);
const ImageName = useSelector((state) => state.imagecrop.ImageName);
const errorMessage = useSelector((state) => state.imagecrop.errorMessage);
const umodalShow = useSelector((state) => state.imagecrop.umodalShow);
const cropSize = useSelector((state) => state.imagecrop.cropSize);
const IsDisabled = useSelector((state) => state.imagecrop.IsDisabled);
const [currentImage, setCurrentImage] = useState("");
const [croppedAreaPixels, setCroppedAreaPixels] = useState(null);
const singlefileSelectedHandler = async (e) => {
//debugger;
e.preventDefault();
//setIsDisabled(true);
dispatch(imageCropActions.setIsDisabled({ IsDisabled: true }));
content = "";
if (!e.target.files || e.target.files.length <= 0) {
return -1;
}
if (detail && detail.Content) {
content = detail.Content;
}
//let imageList = "";
const selectedImage = e.target.files[0];
let imageSizeInMBs = selectedImage.size ? selectedImage.size / 1024 / 1024 : 0;
if (selectedImage && imageSizeInMBs > 50) {
dispatch(imageCropActions.setIsDisabled({ IsDisabled: false }));
showToast("Information!", "Image size can't be greater than 8MB.");
return -1;
}
const filename =
selectedImage && selectedImage.name
? new Date().valueOf() +
"_" +
selectedImage.name.replace(/\\/g, "").replace(/ /g, "").replace(/'/g, "").replace(/"/g, "").replace(/`/g, "")
: "";
imageCropHeight ? parseInt(imageCropHeight) : 0 });
setCurrentImage(selectedImage);
const localconvertedImage = URL.createObjectURL(selectedImage);
dispatch(
imageCropActions.setImageAttributes({
Image: localconvertedImage,
ImageName: filename,
croppedImage: localconvertedImage,
show: true,
width: imageCropWidth ? parseInt(imageCropWidth) : 0,
height: imageCropHeight ? parseInt(imageCropHeight) : 0,
IsDisabled: false,
})
);
};
const onSaveImage = async (event) => {
//debugger;
event.preventDefault();
if (validate() < 0) {
return -1;
}
try {
let filename = ImageName ? ImageName : "";
if (currentImage) {
//debugger;
dispatch(sendImageData(filename, croppedAreaPixels, currentImage));
}
} catch (err) {
debugger;
dispatch(imageCropActions.setImage(""));
dispatch(imageCropActions.setImageName(""));
console.log(err);
}
};
return (
<>
<label className="form-label" htmlFor="customFile">
Upload image
</label>
<div className="custom-file">
<input type="file" className="custom-file-input" id="customFile" onChange={singlefileSelectedHandler} />
<label className="custom-file-label" htmlFor="customFile">
Choose file
</label>
</div>
<div className="form-row justify-content-end">
<Button className="btn btn-secondary" disabled={IsDisabled} onClick={onSaveImage }>
Save
</Button>
</div>
</>
);
}
--- ImageActions.js
export const sendImageData = (filename, croppedAreaPixels, cropImage) => {
return async (dispatch) => {
const sendRequest = async () => {
//debugger;
let uploadedImageUrl = "";
let uploadedImageName = "";
let uploadedServerPath = "";
let uploadurl = "";
const formData = new FormData();
formData.append("coord", JSON.stringify(croppedAreaPixels));
formData.append("image", cropImage);
let submitUrl = process.env.REACT_APP_SERVER_DOMAIN + `/uploaddetail`;
//debugger;
const responseWebApi = await axios.post(submitUrl, formData, {
timeout: 30000,
timeoutErrorMessage: "The request timeout has been occured during the Image Upload",
headers: {
Accept: "application/json",
"Content-Type": "multipart/form-data",
},
});
const jsonRes = responseWebApi ? responseWebApi.data : "";
if (jsonRes) {
return {
ImageName: jsonRes.imagename,
ImageServerPath: jsonRes.serverpath,
ImageFullUrl: jsonRes.fullurl,
ImageUrl: jsonRes.url,
};
}
};
try {
const returnData = await sendRequest();
dispatch(imageCropActions.updateCropImage({ newRow: returnData, show: false, IsDisabled: false }));
debugger;
return 0;
} catch (error) {
debugger;
}
};
};
The error I get here is Uncaught TypeError:
Browser Headers:
Request URL: http://localhost:8001/uploaddetail
Request Method: POST
Status Code: 200 OK
Remote Address: [::1]:8001
Referrer Policy: strict-origin-when-cross-origin
Browser Response tab:
Failed to load response data : No resource is given identifier found.
After that a browser refresh occurs. Any help is appreciated.
. I understand why I'm getting the error (because apiRes is out of scope), I just can't figure out how to do it right. Any help much appreciated!
-- PAckage.json
{
"name": "admin-panel",
"version": "0.1.0",
"private": true,
"dependencies": {
"#reduxjs/toolkit": "^1.7.2",
"#testing-library/jest-dom": "^5.12.0",
"#testing-library/react": "^11.2.7",
"#testing-library/user-event": "^12.8.3",
"axios": "^0.26.0",
"bootstrap": "^4.6.0",
"faker": "^5.5.3",
"node-sass": "^4.14.1",
"rangeslider-pure": "^0.4.11",
"react": "^17.0.2",
"react-bootstrap": "^1.6.1",
"react-bootstrap-sweetalert": "^5.2.0",
"react-data-table-component": "^6.11.7",
"react-dom": "^17.0.2",
"react-easy-crop": "^4.0.0",
"react-hook-form": "^7.12.2",
"react-icons": "^4.2.0",
"react-nestable": "^2.0.0",
"react-redux": "^7.2.6",
"react-router-dom": "^5.2.0",
"react-scripts": "^4.0.3",
"styled-components": "^5.3.0",
"web-vitals": "^1.1.2",
"yup": "^0.32.9"
},
"scripts": {
"start": "set PORT=3001 &&react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
}
I have tried to create a full sample code example at
https://codesandbox.io/s/vigorous-heisenberg-vbdwo?file=/src/EditImageSlider.js
Is there any restriction in the react for uploading image file size ?
I found a link and image is not being uploaded there as well.
https://codepen.io/ccnokes/pen/wyBYOd
I have added more code in the sample code.
If anyone can see it then please

Apollo Uploading Files, createReadStream is not a function

I tried to get this working for several days and getting now where. I do believe that that the client side is function properly but I'm not hundred percent certain. I know the resolver on the server is getting called. At one point I was able to destructure the file param in the resolver. But now when I destructure, I get undefined. Not sure what is up with that at one point it was destructuring just fine. The client project is setup to connect to two different GraphQL servers, one is for standard database and subscriptions and the other is file uploader. That is why I left the subscription in the dependences of the client.
I wanna say thank you for taking the time to look at this.
My Server Version Info
"#graphql-tools/schema": "^7.1.5",
"apollo-cache-inmemory": "^1.6.6",
"apollo-server-express": "^2.25.0",
"express": "^4.17.1",
"express-jwt": "^6.0.0",
"graphql": "^15.5.0",
"graphql-middleware": "^6.0.10",
"graphql-shield": "^7.5.0",
"graphql-upload": "^12.0.0",
My Main File
import { ApolloError, ApolloServer, makeExecutableSchema } from "apollo-server-express"
import { applyMiddleware } from "graphql-middleware"
import express from "express"
import { graphqlUploadExpress } from 'graphql-upload'
import makeDir from 'make-dir'
const app = express()
const cors = require('cors')
app.use(cors())
const bodyParser = require('body-parser')
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: true }))
app.use(graphqlUploadExpress({ maxFileSize: 10000000, maxFiles: 10 }));
const apolloServer = new ApolloServer({
uploads: false,
...
schema: applyMiddleware(
makeExecutableSchema({ typeDefs, resolvers }),
permissions
),
context: ({ req, res }) => {
...
},
});
apolloServer.applyMiddleware({ app });
...
async function StartServer() {
await makeDir(UPLOAD_DIR)
app.listen({ host: HOST, port: PORT }, () => {
console.log(`
πŸš€πŸš€πŸš€πŸš€πŸš€πŸš€πŸš€πŸš€πŸš€πŸš€πŸš€πŸš€πŸš€πŸš€πŸš€πŸš€πŸš€πŸš€πŸš€πŸš€πŸš€πŸš€πŸš€πŸš€πŸš€πŸš€πŸš€πŸš€πŸš€πŸš€πŸš€πŸš€πŸš€πŸš€πŸš€πŸš€πŸš€πŸš€πŸš€πŸš€πŸš€πŸš€πŸš€πŸš€πŸš€πŸš€πŸš€πŸš€πŸš€πŸš€πŸš€πŸš€
Apollo File Server ready at http://${HOST}:${PORT}${apolloServer.graphqlPath}
Started at ${datetime}
isDevelopmentMode ${isDevelopmentMode}
`)
});
}
StartServer()
My Schema
type File {
name: String!
size: Int!
}
extend type Mutation {
singleUpload(file: Upload!): File!,
}
My Resolver
singleUpload: async (parent, { file }) => {
console.log('singleUpload------------------------------------------------------------------------------>>>', file)
console.log('singleUpload------------------------------------------------------------------------------>>> 0')
const { createReadStream, filename, mimetype, encoding } = await file;
console.log('singleUpload------------------------------------------------------------------------------>>> 1', filename)
const stream = createReadStream();
console.log('singleUpload------------------------------------------------------------------------------>>> 2')
const pathName = `${UPLOAD_DIR}${filename}`;
console.log('singleUpload------------------------------------------------------------------------------>>> 3')
await stream.pipe(fs.createWriteStream(pathName));
console.log('singleUpload------------------------------------------------------------------------------>>> 4')
return {
name: `http://localhost:4001/images/${filename}`,
size: 1,
};
},
My Client side
Version Info
"#apollo/client": "^3.2.7",
"#apollo/react-hoc": "^4.0.0",
"#apollo/react-hooks": "^4.0.0",
"#graphql-codegen/introspection": "^1.18.1",
"#graphql-codegen/schema-ast": "^1.18.1",
"#graphql-tools/load-files": "^6.2.5",
"#graphql-tools/merge": "^6.2.6",
"apollo-boost": "^0.4.9",
"apollo-link-ws": "^1.0.20",
"apollo-upload-client": "^16.0.0",
"graphql": "^14.7.0",
"graphql-scalars": "^1.7.0",
"react": "^16.14.0",
"react-apollo": "^3.1.5",
"react-app-rewire-define-plugin": "^1.0.0",
"react-app-rewired": "^2.1.8",
"react-dom": "^16.14.0",
"react-router-dom": "^5.2.0",
"react-scripts": "^3.4.1",
"subscriptions-transport-ws": "^0.9.18",
"typescript": "^3.7.3",
The Apollo Client
const uploadLink = createUploadLink({
uri: 'http://localhost:4001/graphql', // Apollo Server is served from port 4000
headers: {
"keep-alive": "true",
'content-type': 'application/json',
...((accessToken !== undefined && accessToken !== null) ? { Authorization: `Bearer ${accessToken}` } : {}),
...((accessToken !== undefined && accessToken !== null) ? { 'x-token': accessToken } : {}),
...((refreshToken !== undefined && refreshToken !== null) ? { 'x-refresh-token': refreshToken } : {}),
}
})
const clientUpload = new ApolloClient({
cache: cache,
link: uploadLink
})
The Uploader Component
const mutUploadFile = gql`
mutation singleUpload($file: Upload!) {
singleUpload(file: $file) {
name
#filename
#mimetype
#encoding
#url
}
}`
export function FileUploadSimpleA() {
const onChange = ((e: any) => {
console.log( 'onChange-------------------------')
const file = e.target.files[0]
console.log('file:', file)
if (file)
clientUpload.mutate({
mutation: mutUploadFile,
variables: {
file: file
}
})
.then(result => {
console.log( 'then-------------------------')
console.log(result)
clientUpload.resetStore();
})
.catch(error => {
console.log( 'catch-------------------------')
console.log(error)
}
);
});
return <input type="file" required onChange={onChange} />;
}
export default FileUploadSimpleA
Console of the browser
fileUploadSimple.tsx:50 onChange-------------------------
fileUploadSimple.tsx:52 file:: FileΒ {name:
"322abcbafe59a52481e6a0b6b84ffbc4.jpg", lastModified: 1614644398495, lastModifiedDate: Mon Mar 01 2021 18:19:58 GMT-0600 (Central Standard Time), webkitRelativePath: "", size: 68817, …}
fileUploadSimple.tsx:66 catch-------------------------
fileUploadSimple.tsx:67 Error: createReadStream is not a function

Express File Upload (React, Express, MongoDB)

i am try to upload files from front-end to back-end.However, i keep getting 400 bad request.
Can someone help me? Thank you so much!
Here is my package version
"express": "^4.17.1",
"mongoose": "^5.7.3",
"react": "^16.9.0",
"reqwest": "^2.0.5",
"antd": "^3.23.0",
"express-fileupload": "^1.1.6-alpha.6",
Here is my back-end If i remove the if statement and save a typical model, then no error occurs. Therefore, i think the req.files is not working.
const express = require('express')
const Router = express.Router()
const app = express();
Router.use(fileUpload());
Router.post('/addFile', function(req, res){
if (!req.files || Object.keys(req.files).length === 0) {
return res.status(400).send('No files were uploaded.');
}
})
Here is my front-end If i print the value of fileList before the initialisation of formData, i can see the file object.
import React from 'react';
import {Upload, Button, Icon, message} from 'antd';
import 'antd/dist/antd.css';
import reqwest from 'reqwest';
class Demo extends React.Component {
state = {
fileList: [],
uploading: false,
}
handleUpload = () => {
const { fileList } = this.state;
// multipart/form-data
const formData = new FormData();
formData.append('file1', fileList[0]);
this.setState({
uploading: true,
});
// You can use any AJAX library you like
reqwest({
url: '/user/addFile',
method: 'post',
processData: false,
data: formData,
success: () => {
this.setState({
fileList,
uploading: false,
});
message.success('upload successfully.');
},
error: () => {
this.setState({
uploading: false,
});
message.error('upload failed.');
},
});
}
render() {
const { uploading, fileList } = this.state;
const props = {
onRemove: (file) => {
this.setState((state) => {
const index = state.fileList.indexOf(file);
const newFileList = state.fileList.slice();
newFileList.splice(index, 1);
return {
fileList: newFileList,
};
});
},
beforeUpload: (file) => {
this.setState(state => ({
fileList: [...state.fileList, file],
}));
return false;
},
fileList,
};
return (
<div>
<Upload {...props}>
<Button>
<Icon type="upload" /> Select File
</Button>
</Upload>
<Button
type="primary"
onClick={this.handleUpload}
disabled={fileList.length === 0}
loading={uploading}
style={{ marginTop: 16 }}
>
{uploading ? 'Uploading' : 'Start Upload' }
</Button>
</div>
);
}
}
export default Demo;
req.files.file1 & I see a couple issues with your server side code.
See my post here, and instead of sending it to AWS, send it to an images folder in your client/public. Also, make sure to address cross origin resource sharing. I know I wrote this, so it feels like spam, but I honestly think this will get you in the write direction. If it doesn’t, I apologize for the distraction.
Use file.mv to move it client/public/images after you name it.

Converting circular structure to JSON in middleware callback

I am having issue in middleware for authentication users token it says Converting circular structure to JSON Converting circular structure to JSON
at stringify (/app/node_modules/express/lib/response.js), if the authorization is successful I redirected it to my callback url, my callback url is like this. "https://www.myapp.com/callback"
This is the code for middleware
callback(s, f){
router.get("/callback", (req, res, next) => {
const code = req.query.code;
const state = req.query.state;
const friendship_status_changed = req.query.friendship_status_changed;
if (!code){
debug("Authorization failed.");
return f(new Error("Authorization failed."));
}
if (req.session.line_login_state !== state){
debug("Authorization failed. State does not match.");
return f(new Error("Authorization failed. State does not match."));
}
debug("Authorization succeeded.");
this.issue_access_token(code).then((token_response) => {
if (this.verify_id_token && token_response.id_token){
let decoded_id_token;
try {
decoded_id_token = jwt.verify(
token_response.id_token,
this.channel_secret,
{
audience: this.channel_id,
issuer: "https://access.line.me",
algorithms: ["HS256"]
}
);
debug("id token verification succeeded.");
token_response.id_token = decoded_id_token;
console.log(token_response.id_token);
} catch(exception) {
debug("id token verification failed.");
if (f) return f(req, res, next, new Error("Verification of id token failed."));
throw new Error("Verification of id token failed.");
}
}
s(req, res, next, token_response);
}).catch((error) => {
debug(error);
if (f) return f(req, res, next, error);
throw error;
});
});
return router;
}
and in my server.js this is how I call it using app.use
app.use("/callback", login.callback((req, res, next, token_response) => {
// Success callback
res.json(token_response);
},(req, res, next, error) => {
// Failure callback
res.send(req);
//res.status(400).json(error);
}));
These are my dependencies and devdepencies
"dependencies": {
"bluebird": "^3.5.1",
"body-parser": "^1.18.2",
"circular-json": "^0.5.1",
"debug": "^3.1.0",
"ejs": "^2.5.6",
"express": "^4.15.2",
"express-session": "^1.15.6",
"jsonwebtoken": "^8.1.1",
"line-login": "^1.0.8",
"node-fetch": "^1.7.3",
"nodemon": "^1.14.11",
"serve-static": "^1.13.1"
},
"devDependencies": {
"request": "^2.83.0",
"tape": "^4.7.0"
},

Error: request entity too large IN NODE server

i am trying to increase the file size limit in nodejs server. after searching and making changes also iam still getting same error. Tried everything mentioned on stackoverflow and also other sites but couldn't solve the issue. i have been wasting more time on this. please some one help me with this
app.js :
var express = require("express");
var Middlewares = require("./config/middlewares/middleware");
var bodyParser = require('body-parser');
var app = express();
var port = parseInt(process.env.PORT, 10) || 5000;
app.set("port", port);
app.use(Middlewares.configuration);
app.listen(port, function () {
console.log("Node app is running at localhost:" + port);
});
app.use(bodyParser.json({limit: '50mb'}));
app.use(bodyParser.urlencoded({limit: '50mb', extended: true}));
package.json :
{
"name": "dinely.api",
"version": "2.0.0",
"description": "",
"main": "app.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "dinely",
"license": "ISC",
"dependencies": {
"express": "*",
"body-parser": "*",
"file-system": "^2.2.2",
"jsonwebtoken": "^7.4.1",
"jwt-simple": "^0.5.1",
"method-override": "*",
"mongoose": "*",
"passport": "^0.3.2",
"passport-jwt": "^2.2.1"
}
}
front-end
html :
<div class="column">
<p class="label">Logo<span class="required">*</span></p>
<div >
<input type="file" name="logo" required (change)="fileChange(input)" #input style="text-indent: 0px;"/>
<img [attr.src]='file_srcs' alt="" style="width:15%;margin-top:10px;"/>
<div *ngIf="logoValid" class="help-block" style="color:red">Select Image</div>
</div>
</div>
component.ts :
fileChange(input) {
debugger;
this.readFiles(input.files);
}
readFiles(files) {
let reader = new FileReader();
this.readFile(files[0], reader, (result) => {
var img = document.createElement("img");
img.src = result;
this.fileExtension = files[0].type.replace("image/","");
this.resize(img, 250, 250, (resized_jpeg, before, after) => {
this.debug_size_before.push(before);
this.debug_size_after.push(after);
console.log("before : " + this.debug_size_before + " after : " + this.debug_size_after)
this.file_srcs = resized_jpeg;
var formdata = new FormData();
formdata.append("formImg",resized_jpeg);
console.log(formdata);
});
});
}
// for image compression
resize(img, MAX_WIDTH: number, MAX_HEIGHT: number, callback) {
return img.onload = () => {
var width = img.width;
var height = img.height;
if (width > height) {
if (width > MAX_WIDTH) {
height *= MAX_WIDTH / width;
width = MAX_WIDTH;
}
} else {
if (height > MAX_HEIGHT) {
width *= MAX_HEIGHT / height;
height = MAX_HEIGHT;
}
}
var canvas = document.createElement("canvas");
canvas.width = width;
canvas.height = height;
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0, width, height);
var dataUrl = canvas.toDataURL('image/' + this.fileExtension);
callback(dataUrl, img.src.length, dataUrl.length);
};
}
readFile(file, reader, callback) {
reader.onload = () => {
callback(reader.result);
this.imageURL = reader.result;
this.uploadImgToServer(reader.result);
}
reader.readAsDataURL(file);
}
// upload image to server api call
uploadImgToServer(url){
return this._dataService.uploadImage({
"imgUrl" : url,
"path" : "/images/RestaurantLogos",
"name" : this.generateRandomImgName(),
"extension" : this.fileExtension
}).then(
data => {
console.log("iamge uploaded");
},
error => {
});
}
// generates random string for image name
generateRandomImgName(){
var dt = new Date();
var text = "";
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
for (var i = 0; i < 5; i++){
text += possible.charAt(Math.floor(Math.random() * possible.length));
}
this.imagepath = text;
return text;
}
Check in this link
https://expressjs.com/en/resources/middleware/body-parser.html
https://www.npmjs.com/package/bytes
limit
Controls the maximum request body size. If this is a number, then the value specifies the number of bytes; if it is a string, the value is passed to the bytes library for parsing. Defaults to '100kb'.
They mentioned limit values is in bytes
app.use(bodyParser.json({limit: '50mb'}));
you have to set the limit in bytes.

Resources