I try to create a redux-react app where the users can import an csv-file that later is stored in a database. Right now I am working on the frontend where I want to create a code where the user can chose a csv file from their computer that they want to download and then the file is sent to the backend. I have therfore used the csvReader to read the csv-file but I don't know how to send the data to the backend. I am using nestJS in the backend. I want to send the whole csv-file in one go but i dont know how to tackle the problem. I am a beginner :))) Do you know how to solve my problem?
I can't help you with react but maybe this NestJS part can help you. You can use multer to config your api and setting a store path.
Create multer options
// multer.ts
const excelMimeTypes = [
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
'application/wps-office.xlsx',
'application/vnd.ms-excel',
];
export const multerOptions = {
fileFilter: (req: any, file: any, cb: any) => {
const mimeType = excelMimeTypes.find(im => im === file.mimetype);
if (mimeType) {
cb(null, true);
} else {
cb(new HttpException(`Unsupported file type ${extname(file.originalname)}`, HttpStatus.BAD_REQUEST), false);
}
},
storage: diskStorage({
destination: (req: any, file: any, cb: any) => {
const uploadPath = '/upload'; // use env var
if (!existsSync(uploadPath)) {
mkdirSync(uploadPath); // create if not exists
}
cb(null, uploadPath);
},
filename: (req: any, file: any, cb: any) => {
cb(null, file.originalname);
},
}),
};
Import multerOption recent created and use FileInterceptor and UploadedFile decorator to get the file.
#Post()
#UseInterceptors(FileInterceptor('file', multerOptions))
uploadFile(#UploadedFile() file) {
console.log(file) // call service or whathever to manage uploaded file.. handleFile in the example below..
}
Manage file (example) using xlsx library.
handleFile(file: any): Promise<any> {
return new Promise(async (resolve: (result: any) => void, reject: (reason: any) => void): Promise<void> => {
try {
const workbook = XLSX.readFile(`${uploadLocation}/${file.filename}`);
resolve(workbook.Sheets[sheetName]);
} catch (error) {
reject(error);
}
});
}
I hope it helps!
Related
I'm having troubles with node 16 and ES6. I'm trying to make a upload file controller but i'm stuck with req.file.stream which is undefined
I'm using multer to handle upload files.
The first issue was __dirname undefined that I was able to fix with path and New Url.
The error I got with pipeline
node:internal/process/promises:246
triggerUncaughtException(err, true /* fromPromise */);
^
TypeError [ERR_INVALID_ARG_TYPE]: The "source" argument must be of type function or an instance of Stream, Iterable, or AsyncIterable. Received undefined
my userRoutes.js
import express from "express";
import { signin, signup, logout } from "../Controller/AuthController.js";
import {
getUsers,
getUser,
updateUser,
deleteUser,
follow,
unfollow,
} from "../Controller/UserController.js";
import { upload } from "../Controller/UploadController.js";
import multer from "multer";
const router = express.Router();
// Auth
router.post("/signin", signin);
router.post("/signup", signup);
router.post("/logout", logout);
// users
router.get("/", getUsers);
router.get("/:id", getUser);
router.patch("/:id", updateUser);
router.delete("/:id", deleteUser);
router.patch("/follow/:id", follow);
router.patch("/unfollow/:id", unfollow);
// upload
router.post("/upload", multer().single("file"), upload);
export default router;
And my UploadController.js
import fs from "fs";
import { promisify } from "util";
import stream from "stream";
const pipeline = promisify(stream.pipeline);
// const { uploadErrors } = require("../utils/errors.utils");
import path from "path";
const __dirname = path.dirname(new URL(import.meta.url).pathname);
export const upload = async (req, res) => {
try {
// console.log(req.file);
console.log(__dirname);
if (
!req.file.mimetype == "image/jpg" ||
!req.file.mimetype == "image/png" ||
!req.file.mimetype == "image/jpeg"
)
throw Error("invalid file");
if (req.file.size > 2818128) throw Error("max size");
} catch (err) {
const errors = uploadErrors(err);
return res.status(201).json({ err });
}
const fileName = req.body.name + ".jpg";
await pipeline(
req.file.stream,
fs.createWriteStream(
`${__dirname}/../client/public/uploads/profil/${fileName}`
)
);
try {
await User.findByIdAndUpdate(
req.body.userId,
{ $set: { picture: "./uploads/profil/" + fileName } },
{ new: true, upsert: true, setDefaultsOnInsert: true },
(err, docs) => {
if (!err) return res.send(docs);
else return res.status(500).send({ message: err });
}
);
} catch (err) {
return res.status(500).send({ message: err });
}
};
Multer gives you the file as a Buffer, not a Stream. req.file.stream is not valid property, but req.file.buffer is: https://github.com/expressjs/multer#file-information.
From the look of your code, you're trying to save the file on disk. You can use multer's DiskStorage for that. Create a storage instance and pass it to the multer instance as a configuration:
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, `${__dirname}/../client/public/uploads/profil/`);
},
filename: function (req, file, cb) {
cb(null, req.body.name + '.jpg');
},
});
const upload = multer({ storage });
router.post('/upload', upload.single('file'), upload);
Have a look at this free Request Parsing in Node.js Guide for working with file uploads in Node.js.
if you want to use req.file.stream, you will need to install this version of multer:
npm install --save multer#^2.0.0-rc.1
and your code will work perfectly, just change your req.file.mimetype to req.file.detectedMimeType !!
i want to write to a JSON file so i used react-native-fs
here is the code:
const add = (n, p, pr) => {
var RNFS = require('react-native-fs');
var filePath = RNFS.DocumentDirectoryPath + '/items.json';
RNFS.writeFile(filePath, '{name:hello}', 'utf8')
.then((success) => {
console.log('SUCCESS');
})
.catch((err) => {
console.log(err.message);
});
};
it log success but didn't update the file any ideas?
Your file is updating successfully and if you want to check it please run the following code after your file is written. You will see the file's path and data of your saved file.
// get a list of files and directories in the main bundle
RNFS.readDir(RNFS.DocumentDirectoryPath)
.then((result) => {
console.log('GOT RESULT', result);
// stat the first file
return Promise.all([RNFS.stat(result[0].path), result[0].path]);
})
.then((statResult) => {
if (statResult[0].isFile()) {
// if we have a file, read it
return RNFS.readFile(statResult[1], 'utf8');
}
return 'no file';
})
.then((contents) => {
// log the file contents
console.log("contents");
console.log(contents); // You will see the updated content here which is "{name:hello}"
})
.catch((err) => {
console.log(err.message, err.code);
});
I try to fetch a local json file in my project.
Tried the following:
import axios from 'axios';
import userDataJson from './../data/userData.json';
export const userDataControllerMixin = {
data() {
return {
users: [],
};
},
mounted() {
this.getUsers();
},
methods: {
getUsers() {
// TODO: load userObj.json initial to prevent reset the userData.json all the time
fetch(userDataJson)
.then((response) => {
console.log(response);
}).catch((err) => {
console.log(err);
});
};
i also tried it with axios before but they all lead into this error msg:
GET http://localhost:9080/[object%20Object] 404 (Not Found)
What am i doing wrong? Looks like a config issue.
You dont need to call fetch method anymore since you are importing your json data from the file. What you can do is, since you are already importing the json data, then when the component is mounted just assign the json data to the user array:
data() {
return {
users: [],
};
},
mounted() {
this.users = JSON.parse(userDataJson)
},
....
}
I have an API that provides me XML data, and i want to convert that XML data from the API into JSON. Can anyone help me wiht that problem?
I'm using Expo to creat a app. I tried to use nodemoduls, but when i tried that I alwas get an error "It failed because React Native does not include the Node standard library" The code belwo dosen't work
import { View, Text, ActivityIndicator } from 'react-native'
import { fetch } from "fetch";
const furl = 'https://skimap.org/Regions/view/346.xml';
const xmlToJson = require('xml-to-json-stream');
const parser = xmlToJson({attributeMode: true});
export default class RegionList extends PureComponent {
state = { regions: [] };
async componentWillMount() {
fetch(furl).then(response => parser.xmlToJson(response, (err,json)=>{
if(err){
console.log(err);
}
}))
.then( (response) => this.setState({regions: response}));
}
Try this:
import {Xml2Json} from 'react-native-xml-to-json';
fetch(furl).then(response =>
Xml2Json.toJson(response, data => {
console.log("Data = ", data);
}).then( (response) => this.setState({regions: data})
);
I've made a GraphQL backend using Apollo Server, Sequelize (for the ORM), MySQL (DB) and Express (Web Server).
I have also added subscriptions, which the problem is there.
I can't even reach the WS endpoint using a websocket tester.
Can someone review my code and tell me what the problem is? I looked in the docs, other stackoverflow questions and I can't find any solution.
The code: https://github.com/seklyza/graphqlsubscriptions
Thanks for everyone
I think you have to make 2 Servers one for the app which uses the express server and one for the websocket. It could look like this.
GraphQL express server:
...
graphQLServer = express();
const GRAPHQL_PORT = 4000;
graphQLServer.use('/graphql', bodyParser.json(), graphqlExpress((request) => {
return {
schema: executableSchema,
};
}));
graphQLServer.use('/graphiql', graphiqlExpress({
endpointURL: '/graphql',
}));
graphQLServer.listen(GRAPHQL_PORT, () => {
console.log(`GraphQL Server is now running on http://localhost:${GRAPHQL_PORT}/graphql`); // eslint-disable-line no-console
});
...
websocket server for subscriptions:
...
const WS_PORT = 8080;
const websocketServer = createServer((request, response) => {
response.writeHead(404);
response.end();
});
websocketServer.listen(WS_PORT, () => console.log( // eslint-disable-line no-console
`Websocket Server is now running on http://localhost:${WS_PORT}`
));
const subscriptionManager = new SubscriptionManager({
schema: executableSchema,
pubsub: pubsub,
setupFunctions: { /* your subscription channels */ },
});
subscriptionServer = new SubscriptionServer({
subscriptionManager: subscriptionManager
}, {
server: websocketServer,
path: '/',
});
...
And you need some sort of publication subscription service, we use pubSub. It is included in the server file and looks like this:
import {
PubSub
} from 'graphql-subscriptions';
const pubsub = new PubSub();
export {
pubsub
};
You can create some web socket server wrapper which implements start method which will be responsible for creating and running the WSServer, as well as it will create a SubscriptionServer with use of SubscriptionManager
// in subscription.js
import { PubSub, SubscriptionManager } from 'graphql-subscriptions';
const pubSub = new PubSub();
let subscriptionManagerOptions = {
schema: schema, // this is your graphql schema
setupFunctions: {
// here come your setup functions
},
pubSub: pubSub
};
const subscriptionManager = new SubscriptionManager(subscriptionManagerOptions);
export { pubSub, subscriptionManager };
After we have the subscriptionManager created, we can now implement the WSServer
import { createServer } from 'http';
import { SubscriptionServer } from 'subscription-transport-ws';
import { subscriptionManager } from './subscription';
const webSocketServerWrapper = {
start: function(port){
const webSocketServer = createServer((request, response) => {
response.writeHead(404);
response.end();
});
webSocketServer.listen(port, () => {
console.log('WSServer listening on port ' + port);
});
new SubscriptionServer({
subscriptionManager,
onSubscribe: (message, options, request) => {
return Promise.resolve(Object.assign({}, options, {}));
}
}, webSocketServer);
}
};
export default webSocketServerWrapper;
Now you can import the webSocketServerWrapper in the initialisation file like index.js and simply run webSocketServerWrapper.start(PORT);
Here, the second answer which I wrote, you can find a code responsible for creating example subscription and how it should be handled.