uploading and deleting files using react filepond and firebase storage - reactjs

I am new into this. So i found this example code to upload files to firebase storage using file pond. It works great when uploading the file.
import * as firebase from "firebase/app";
import "firebase/storage";
import shortid from "shortid";
import * as React from "react";
import { FilePond, registerPlugin } from "react-filepond";
import "filepond/dist/filepond.min.css";
import FilePondPluginImageExifOrientation from "filepond-plugin-image-exif-orientation";
import FilePondPluginImagePreview from "filepond-plugin-image-preview";
import "filepond-plugin-image-preview/dist/filepond-plugin-image-preview.css";
import debug from "debug";
const log = debug("app:image");
registerPlugin(FilePondPluginImageExifOrientation, FilePondPluginImagePreview);
const storage = firebase.storage().ref();
export default function ImageUpload({
onRequestSave,
onRequestClear,
defaultFiles = []
}) {
const [files, setFiles] = React.useState(defaultFiles);
const ref = React.useRef(null);
return (
<FilePond
files={files}
ref={ref}
allowMultiple={false}
maxFiles={1}
server={{
process: (
_fieldName,
file,
_metadata,
load,
error,
progress,
_abort
) => {
const id = shortid.generate();
const task = storage.child("images/" + id).put(file, {
contentType: "image/jpeg"
});
task.on(
firebase.storage.TaskEvent.STATE_CHANGED,
snap => {
log("progress: %o", snap);
progress(true, snap.bytesTransferred, snap.totalBytes);
},
err => {
log("error: %o", err);
error(err.message);
},
() => {
log("DONE");
load(id);
// onRequestSave(id);
}
);
},
load: (source, load, error, progress, abort) => {
progress(true, 0, 1024);
storage
.child("images/" + source)
.getDownloadURL()
.then(url => {
let xhr = new XMLHttpRequest();
xhr.responseType = "blob";
xhr.onload = function(event) {
let blob = xhr.response;
log("loaded URL: %s", url);
load(blob);
};
xhr.open("GET", url);
xhr.send();
})
.catch(err => {
error(err.message);
abort();
});
}
}}
/>
);
}
If i add the following prop,:
instantUpload={false}
then FilePond will not automatically upload. But I want to write three functions:
handleUpload, handleRead and handleDelete :
to save, view and delete files. Can someone guide me into achieving that?

Related

Error: 'downloadCSV' not found in 'rekognitionActions' and 'fs' not found in 'actions' when trying to export functions in React-app for Amazon AWS S3

I am currently working on a React-app front-end for Amazon AWS S3. The goal of the project is to allow a user to upload multiple images to a S3 bucket, and then call a Lambda function to send the uploaded images to Amazon Rekognition for labeling. The results will then be returned in a CSV file that the user can download as the output.
However, I am currently encountering an issue where I am getting the following error message:
Failed to compile.
export 'downloadCSV' (reexported as 'downloadCSV') was not found in './rekognitionActions' (possible exports: addFacesToCollection, createCollection, detectLabels, getLabeledResults, handleFileUpload, indexFaces, parseCSV, searchFaces, searchFacesByImage, uploadImages, uploadImagesAndGetLabels)
ERROR in ./src/components/actions/index.js 5:0-84
export 'downloadCSV' (reexported as 'downloadCSV') was not found in './rekognitionActions' (possible exports: addFacesToCollection, createCollection, detectLabels, getLabeledResults, handleFileUpload, indexFaces, parseCSV, searchFaces, searchFacesByImage, uploadImages, uploadImagesAndGetLabels)
ERROR in ./src/components/actions/rekognitionActions.js 4:0-38
Module not found: Error: Can't resolve 'fs' in 'C:\Users\luisj\Desktop\awsapp\awsapp\src\components\actions'
I am also receiving
Module not found: Error: Can't resolve 'fs' in 'C:\Users\luisj\Desktop\awsapp\awsapp\src\components\actions'
I am unsure of what is causing this issue and would greatly appreciate any help in resolving it.
rekognitionActions.js
import AWS from 'aws-sdk';
import { createReadStream } from 'fs';
import Papa from 'papaparse';
const rekognition = new AWS.Rekognition({
accessKeyId: process.env.REACT_APP_AWS_ACCESS_KEY_ID,
secretAccessKey: process.env.REACT_APP_AWS_SECRET_ACCESS_KEY,
});
const s3 = new AWS.S3({
accessKeyId: process.env.REACT_APP_AWS_ACCESS_KEY_ID,
secretAccessKey: process.env.REACT_APP_AWS_SECRET_ACCESS_KEY,
});
export const detectLabels = async (image) => {
const params = {
Image: {
S3Object: {
Bucket: process.env.REACT_APP_AWS_S3_BUCKET,
Name: image,
},
},
MaxLabels: 10,
MinConfidence: 80,
};
const data = await rekognition.detectLabels(params).promise();
return data.Labels;
};
export const createCollection = async (collectionId) => {
const params = {
CollectionId: collectionId,
};
await rekognition.createCollection(params).promise();
};
export const indexFaces = async (collectionId, image) => {
const params = {
CollectionId: collectionId,
Image: {
S3Object: {
Bucket: process.env.REACT_APP_AWS_S3_BUCKET,
Name: image,
},
},
};
const data = await rekognition.indexFaces(params).promise();
return data.FaceRecords;
};
export const searchFacesByImage = async (collectionId, image) => {
const params = {
CollectionId: collectionId,
Image: {
S3Object: {
Bucket: process.env.REACT_APP_AWS_S3_BUCKET,
Name: image,
},
},
MaxFaces: 10,
FaceMatchThreshold: 80,
};
const data = await rekognition.searchFacesByImage(params).promise();
return data.FaceMatches;
};
export const uploadImages = async (images) => {
const uploadPromises = images.map(async (image) => {
const params = {
Bucket: process.env.REACT_APP_AWS_S3_BUCKET,
Key: image.name,
Body: image,
};
await s3.upload(params).promise();
});
await Promise.all(uploadPromises);
};
export const getLabeledResults = async (images) => {
const labelPromises = images.map(async (image) => {
const labels = await detectLabels(image.name);
return { imageName: image.name, labels };
});
const labeledResults = await Promise.all(labelPromises);
return labeledResults;
};
export const uploadImagesAndGetLabels = async (images) => {
await uploadImages(images);
const labeledResults = await getLabeledResults(images);
return labeledResults;
};
export const parseCSV = async (file) => {
return new Promise((resolve, reject) => {
Papa.parse(createReadStream(file), {
header: true,
complete: (results) => {
resolve(results.data);
},
error: (error) => {
reject(error);
},
});
});
};
export const addFacesToCollection = async (collectionId, images) => {
const indexFacePromises = images.map(async (image) => {
const indexedFaces = await indexFaces(collectionId, image.name);
return { imageName: image.name, indexedFaces };
});
const indexedResults = await Promise.all(indexFacePromises);
return indexedResults;
};
export const searchFaces = async (collectionId, images) => {
const searchFacePromises = images.map(async (image) => {
const faceMatches = await searchFacesByImage(collectionId, image.name);
return { imageName: image.name, faceMatches };
});
const searchResults = await Promise.all(searchFacePromises);
return searchResults;
};
export const handleFileUpload = async (file, collectionId) => {
try {
const images = await parseCSV(file);
await uploadImagesAndGetLabels(images);
await createCollection(collectionId);
const indexedResults = await addFacesToCollection(collectionId, images);
const searchResults = await searchFaces(collectionId, images);
return { indexedResults, searchResults };
} catch (error) {
throw error;
}
};
index.js
import * as rekognitionActions from './rekognitionActions';
import * as otherActions from './otherActions';
import { uploadImages, getLabeledResults, downloadCSV } from './actions';
export const { uploadImages, getLabeledResults, downloadCSV } = rekognitionActions;
export const { otherAction1, otherAction2 } = otherActions;
I have made my full project available on my GitHub repository, which can be accessed HERE
I am trying to create a React-app front-end for Amazon AWS S3. The goal of this project is to allow a user to upload multiple images to a S3 bucket, and then call a lambda function to send the uploaded images to Amazon Rekognition for labeling. The results are then returned in a CSV file that the user can download as the output.
I have created the necessary components and actions for this project, but when I try to compile the code, I am getting an error :
Module not found: Error: Can't resolve './components/actions' in 'C:\Users\luisj\Desktop\awsapp\awsapp\src\components'". I am also getting an error that says "export 'downloadCSV' (reexported as 'downloadCSV') was not found in './rekognitionActions' (possible exports: addFacesToCollection, createCollection, detectLabels, getLabeledResults, handleFileUpload, indexFaces, parseCSV, searchFaces, searchFacesByImage, uploadImages, uploadImagesAndGetLabels)". Additionally, there is an error that says "Module not found: Error: Can't resolve 'fs' in 'C:\Users\luisj\Desktop\awsapp\awsapp\src\components\actions'
I was expecting the code to compile without any errors, and for the application to function as intended. However, the errors I am receiving are preventing me from moving forward with the project.
I have tried re-organizing the file structure, double checking the imports and exports in the code, and making sure that all necessary dependencies are installed, but I am still encountering these errors.

Google OAuth components must be used within GoogleOAuthProvider

I want to build my next js project in which i am using
https://www.npmjs.com/package/#react-oauth/google
but when I build it i get the following :
this is layout.js and in _app.js I have all the components wrapped in GoogleOAuthProvider
import { GoogleLogin } from '#react-oauth/google';
import {FcGoogle} from "react-icons/Fc"
import { useGoogleLogin } from '#react-oauth/google';
export default function Layout({ children }) {
const client_id = ""
const responseGoogle = (response) => {
console.log(response);
}
CUTTED (NOT RELEVANT)
const login = useGoogleLogin({
onSuccess: codeResponse => {
const { code } = codeResponse;
console.log(codeResponse)
axios.post("http://localhost:8080/api/create-tokens", { code }).then(response => {
const { res, tokens } = response.data;
const refresh_token = tokens["refresh_token"];
const db = getFirestore(app)
updateDoc(doc(db, 'links', handle), {
refresh_token : refresh_token
})
updateDoc(doc(db, 'users', useruid), {
refresh_token : refresh_token
}).then(
CUTTED (NOT RELEVANT)
)
}).catch(err => {
console.log(err.message);
})
},
onError: errorResponse => console.log(errorResponse),
flow: "auth-code",
scope: "https://www.googleapis.com/auth/calendar"
});
return (
<>
CUTTED (NOT RELEVANT)
</>
)
}
Everything works perfect in dev mode but it does not want to build
I've faced this issue too. So I use 'GoogleLogin' instead of 'useGoogleLogin', then you can custom POST method on 'onSuccess' property.
import { GoogleLogin, GoogleOAuthenProvider} from '#react-oauth/google';
return(
<GoogleOAuthProvider clientId="YOUR CLIENT ID">
<GoogleLogin
onSuccess={handleLogin}
/>
</GoogleOAuthProvider>
The async function will be like...
const handleLogin = async = (credentialResponse) => {
var obj = jwt_decode(credentialResponse.credential);
var data = JSON.stringify(obj);
console.log(data);
const data = {your data to send to server};
const config = {
method: 'POST',
url: 'your backend server or endpoint',
headers: {},
data: data
}
await axios(config)
}
Spending whole day, this solve me out. Just want to share.
You have to wrap your application within GoogleOAuthProvider component. Please keep in mind that you will need your client ID for this.
import { GoogleOAuthProvider } from '#react-oauth/google';
<GoogleOAuthProvider clientId="<your_client_id>">
<SomeComponent />
...
<GoogleLoginButton onClick={handleGoogleLogin}/>
</GoogleOAuthProvider>;

Upload multiple images to separate folder in Next Js [duplicate]

I have a task for uploading images using Next js. API for image uploading has been given and it exists in the same project and when it becomes successful images are stored in a separate directory.
API for image uploading is as follows,
import formidable from "formidable";
import path from "path";
import { renameSync } from "fs";
export const config = {
api: {
bodyParser: false,
},
};
export default async function upload(req, res) {
if (req.method !== "POST") {
return res.status(405).json({ error: "Method not allowed" });
}
const form = new formidable.IncomingForm({
keepExtensions: true,
maxFileSize: 200 * 1024 * 1024,
});
return new Promise((resolve, reject) => {
form.parse(req, async (err, fields, files) => {
if (err) {
res.status(500).json({ error: err.message });
return resolve();
}
if (!files.image) {
res.status(422).json({ error: "Bad request: missing image field" });
return resolve();
}
const ext = path.extname(files.image.path);
const uuid = Math.random().toString(26).slice(2);
await renameSync(files.image.path, `./public/images/${uuid}${ext}`);
res.status(201).json({
uuid,
url: `/images/${uuid}${ext}`,
});
return resolve();
});
});
}
Code for the front-end is mentioned below,
import React from "react";
export default function UploadImage() {
const [imgsSrc, setImgsSrc] = React.useState([]);
const uploadToClient = (e) => {
for (const file of e.target.files) {
setImgsSrc((imgs) => [...imgs, file]);
}
};
const uploadToServer = async () => {
let formData = new FormData();
for (const file of imgsSrc) {
formData.append('image', file, file.name)
}
const response = await fetch("/api/upload", {
method: "POST",
body: formData
});
};
return(
<div>
<h3>Upload photos</h3>
<input onChange={uploadToClient} type="file" name="file" multiple />
<div>
{imgsSrc.map((link) => (
<img src={link} style={{ width: 200, height: 200 }} />
))}
</div>
<button type="submit" onClick={uploadToServer}>Send to server</button>
</div>
)
}
When uploading images I am getting 'error - unhandledRejection: TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received undefined'.
Any suggestion would be highly appreciated!

Converting BLOB (docxtemplater) to PDF - REACT

Hello everyone I am developing a website using React.js and Node.js where I generate a word document from the user's input and thats worked just fine with docxtemplater!
The problem is I want to let the user download the word document direclty as a PDF document but docxtemplater just permit us to save the file as a docx.
To convert the docx, i have the idea to save my blob document in mongodb with gridfs (already done and worked fine) and then get my blob and convert it to pdf (where i'm blocked)
Here is the part of my code for generate my docx and saving the generated word docx in mongodb (i have intentionnaly delete some things not important for this question)
import React, { useState, useEffect } from "react";
import Docxtemplater from "docxtemplater";
import PizZip from "pizzip";
import PizZipUtils from "pizzip/utils/index.js";
import { saveAs } from "file-saver";
import axios from "axios";
function loadFile(url, callback) {
PizZipUtils.getBinaryContent(url, callback);
}
export const DocxFile = ({ formData }) => {
const [file, setFile] = useState(null);
const [currentlyUploading, setCurrentlyUploading] = useState(false);
const [docxId, setDocxId] = useState(null);
const [progress, setProgress] = useState(null);
const [inputContainsFile, setInputContainsFile] = useState(false);
const [template, setTemplate] = useState();
const generateDocument = () => {
loadFile(template, function (error, content) {
if (error) {
throw error;
}
var zip = new PizZip(content);
var doc = new Docxtemplater(zip, {
paragraphLoop: true,
linebreaks: true,
});
doc.setData({
company: formData.general.companyClient,
version: formData.documentVersion,
quote: formData.general.quoteNumber,
HERE MY DATA //Working :)
});
try {
doc.render();
} catch (error) {
function replaceErrors(key, value) {
if (value instanceof Error) {
return Object.getOwnPropertyNames(value).reduce(function (
error,
key
) {
error[key] = value[key];
return error;
},
{});
}
return value;
}
if (error.properties && error.properties.errors instanceof Array) {
const errorMessages = error.properties.errors
.map(function (error) {
return error.properties.explanation;
})
.join("\n");
}
throw error;
}
var out = doc.getZip().generate({
type: "blob",
mimeType:
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
});
saveAs(
out,
`${name}.${documentVersion}.docx`
);
setFile(out);
setInputContainsFile(true);
});
};
const fileUploadHandler = () => {
const fd = new FormData();
fd.append("docx", file, file.name);
axios
.post(`api/docx/upload`, fd, {
onUploadProgress: (ProgressEvent) => {
setProgress((ProgressEvent.loaded / ProgressEvent.total) * 100);
console.log(
"upload progress",
Math.round((ProgressEvent.loaded / ProgressEvent.total) * 100)
);
},
})
.then(({ data }) => {
setDocxId(data);
setFile(null);
setInputContainsFile(false);
setCurrentlyUploading(false);
})
.catch((err) => {
console.log(err);
if (err.response.status === 400) {
const errMsg = err.response.data;
if (errMsg) {
console.log(errMsg);
}
} else {
console.log("other error", err);
setInputContainsFile(false);
setCurrentlyUploading(false);
}
});
};
const handleClick = () => {
if (inputContainsFile) {
setCurrentlyUploading(true);
fileUploadHandler();
}
};
return (
<>
<button
className="modify__button1 enregistrer generator__button"
onClick={generateDocument}
>
Generate the docx
</button>
<label htmlFor="file" onClick={handleClick}>
{file ? <>SUBMIT</> : <></>}
</label>
</>
);
};
This is what i got on mongodb after sending : MongodbBLOB
After that, i will do a get request to get my blob ( i already know how to get my blob) But then, how can i convert it to pdf (and keep the template used for my docx) ?
Update :
I found a package named docx-pdf which allow me to convert my docx to pdf.
But unfortunately, i've got a lot of webpack problems when i compiled (Can't resolve 'fs', 'child_process', 'path') because "webpack < 5 used to include polyfills for node.js core modules by default."
I will try to resolve this and will update this answer if i succeed to convert my docx :)

How can I setup an Apollo client in React for both upload and subscriptions?

I would like to set up a graphql client with React for both uploading file and handle subscriptions from a graphql server.
The file upload and the other queries work well. The problem is with subscriptions. I get in the browser console the following error:
WebSocket connection to 'ws://localhost:3001/subscriptions' failed: Connection closed before receiving a handshake response
I have used apollo-upload-client for file upload and apollo-link-ws for subscriptions.
I can see that subscriptions-transport-ws suggests using createNetworkInterface and addGraphQLSubscriptions but this approach is not compatible with apollo-upload-client that only supports createUploadLink.
I'm stuck. Please help.
I setup my client like this:
import React from 'react';
import ApolloClient from 'apollo-client';
import { ApolloProvider } from 'react-apollo';
import { createUploadLink } from 'apollo-upload-client';
import { InMemoryCache } from 'apollo-cache-inmemory';
import { ApolloLink, Observable, split } from 'apollo-link';
import { WebSocketLink } from 'apollo-link-ws';
import { getMainDefinition } from 'apollo-utilities';
const cache = new InMemoryCache();
const request = async (operation) => {
const token = localStorage.getItem('token');
operation.setContext({
headers: {
authorization: token ? `Bearer ${token}` : '',
},
});
};
const httpLink = createUploadLink({ uri: 'http://localhost:3001/graphql' });
// Create a WebSocket link:
const wsLink = new WebSocketLink({
uri: 'ws://localhost:3001/subscriptions',
options: {
reconnect: true
},
});
// using the ability to split links, you can send data to each link
// depending on what kind of operation is being sent
const link = split(
// split based on operation type
({ query }) => {
const { kind, operation } = getMainDefinition(query);
return kind === 'OperationDefinition' && operation === 'subscription';
},
wsLink,
httpLink,
);
const requestLink = new ApolloLink((operation, forward) =>
new Observable((observer) => {
let handle;
Promise.resolve(operation)
.then(oper => request(oper))
.then(() => {
handle = forward(operation).subscribe({
next: observer.next.bind(observer),
error: observer.error.bind(observer),
complete: observer.complete.bind(observer),
});
})
.catch(observer.error.bind(observer));
return () => {
if (handle) handle.unsubscribe();
};
}));
const apolloClient = new ApolloClient({
link: ApolloLink.from([
requestLink,
link,
]),
cache,
});
export const withApolloClient = App => (
<ApolloProvider client={apolloClient}>
<App client={apolloClient} />
</ApolloProvider>
);
export default apolloClient;
I am using a similar config but instead of importing WebSocketLink from apollo-link-ws I imported it from #apollo/client.
With that setup i had both the subscription and upload working.
import { WebSocketLink } from "#apollo/client/link/ws";
I would suggest to use graphql-server-express like this

Resources