Corrupt image when uploading to Next.js API - multipartform-data

I'm trying to upload an image as form-data to a Nextjs api route. I use the package formidable to parse and save the file in a server folder. For the http request I use postman on the client.
Here ist the backend code:
import formidable from 'formidable';
export const config = {
api: {
bodyParser: false,
},
};
export default async (req, res) => {
const form = new formidable.IncomingForm();
form.on('fileBegin', (name, file) => {
file.path = "./" + file.name
});
form.parse(req, (err, fields, files) => {
console.log( files);
});
res.statusCode = 200
res.end()
};
The image (jpeg) is saved in the folder. However, it appears to be corrupt or damaged.
Here is the original image:
source image
corrupt image

Next.js need the package formidable-serverless instead of formidable
https://github.com/node-formidable/formidable/issues/629

Related

Firebase Storage: Object does not exist

I have the below code in my ReactJS file that is to upLoad a file to Firebase.
async function uploadFile() {
console.log('starting UPLOAD ========');
const blob = await fetch(mediaBlobUrl).then((r) => r.blob());
const path = '/recordings/one';
firebase
.storage()
.ref(path)
.put(blob)
.then(function (snapshot) {
console.log('Uploaded complete');
});
console.log(`====> setURL is ${setURL} <=======`);
storage.ref(path).getDownloadURL().then(setURL);
}
The first time the button is clicked I get this error, but the the second time I click it then it works. Not sure what is going on?
Firebase Storage: Object 'recordings/one' does not exist. (storage/object-not-found)
I did notice when it fails this is the URL it is trying to hit (404). Notice the %2 instead of "/"
https://firebasestorage.googleapis.com/v0/b/buerce.appspot.com/o/recordings%2Fone 404
That's because your getDownloadURL method runs before actually uploading file. Both the put and getDownloadURL method returns promises. Your function is async so I'd recommend using await for both upload and getDownloadURL methods just like you are doing on fetch method.
async function uploadFile() {
console.log('starting UPLOAD ========');
const blob = await fetch(mediaBlobUrl).then((r) => r.blob());
const path = '/recordings/one';
await firebase.storage().ref(path).put(blob)
const setURL = await storage.ref(path).getDownloadURL()
console.log(`====> setURL is ${setURL} <=======`);
}

Express + React | Googleapis - download a file

Im so new on React components and I try to download files from my google drive folder, after a long time currently I have working my API to upload, and get files. My question is, how should I pass the data to download the file on my front end?
How can I get the files from my google drive, and download on react component?
Thanks in advance, and sorry for my explication, I dont know what I currently doing with the file.
Note: This code is just as example to download an image, I want to pass a fileID to download anything, pdfs, docs, png, etc.
Update: After triying differents solutions my api function was completed like this:
google_Ctrl.getDownload = async(req, res) => {
console.log(req.params);
let Google = await drive.files.get(
{fileId: req.params.id,
alt: 'media'},
{ responseType: 'stream' }
).then((request) => {
console.log(request);
fileType = request.headers['content-type'];
fileName = ( "file" + '.' + fileType );
fileData = request.data;
res.set(request.headers)
// res.set("Content-Type", fileType);
// res.set("Content-Disposition", "attachment; filename='archivo.png'");
fileData.pipe(res)
});
}
My function its currently working, when I using api.rest to send a GET Request they provide me my files. But now my problem is on React Component, I read a lot of posts but I did not found the solution, I currently using downloadjs trying this solution, unsuccessfully.
const DownloadFile = () => {
axios.get(process.env.REACT_APP_API_URL + 'google/download/' + "1YtDWD9hNEgCUi8YGQPjV98sULhyM5m8C")
.then((res) => {
console.log(res);
// res.blob()
// fileDownload(res.data, 'filename.png');
download(res.data, "file.png", res.headers['content-type']);
}).catch((error) =>{
console.error(error);
message.error('upload failed.');
});
}
This is my download function on React component, my .txt files works, but when I try to download pdf's, docs, xlsx, etc, dosent work, what can I do?
With Api.rest I tested my api function and it's working, I can download my files from api.rest, but my react functions apparently its badly formatted, I guess.
Okey, after a long time checking the code I found my error on the React Function, if someone is in the same position, here the code working:
API Google:
google_Ctrl.getDownload = async(req, res) => {
console.log(req.params);
console.log(req.body);
let Google = await drive.files.get(
{fileId: req.params.id,
alt: 'media'},
{ responseType: 'stream' }
).then((request) => {
console.log(request);
fileType = request.headers['content-type'];
fileName = ( "file" + '.' + fileType );
fileData = request.data;
// res.set(request.headers)
console.log(fileType);
res.set("Content-Type", fileType);
res.set("Content-Disposition", "attachment; filename='archivo.png'");
fileData.pipe(res)
});
}
React Component:
const DownloadFile = () => {
axios.get(process.env.REACT_APP_API_URL + 'google/download/' + "1YtDWD9hNEgCUi8YGQPjV98sULhyM5m8C",
{responseType: 'blob'})
.then((res) => {
console.log(res);
// res.blob()
fileDownload(res.data, 'filename.png');
// download(res.data, "file.pdf", res.headers['content-type']);
}).catch((error) =>{
console.error(error);
message.error('upload failed.');
});
}
The next step is send the FileID, Filename with the extention and when you recive use that name/extension to save correctly the file :D.

Fetch URL and get the response dat and download the file (file is a zip or excel file)

I need help to extract response data and save them as a gzip file. I have react with the following code. The URL successfully fetched. I want to save the file as zip or excell.
.then((response) => {
saveAs(
new Blob([response.data], {
type:
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;base64,",
}),
"report.xlsx"
);
});
I have file-save
import { saveAs } from "file-saver";

React App deployed on Digital ocean gives 404 Error

I have a validation form on React but on clicking submit m getting "404 Error".
It works perfect on local machine.
//from app.js
handleSubmit = async e => {
e.preventDefault();
const response = await fetch('/api/emailVerifier', {
method: 'POST',
body: this.state,
headers: {
'Content-Type': 'application/json',
},
//body: JSON.stringify({ post: this.state.post }),
});
const body = await response.text();
this.setState({ responseToPost: body });
};
//from server.js
app.post('/api/emailVerifier', async (req, res) => {
console.log(req.body);
const emailValidator = new EmailValidator();
const { wellFormed, validDomain, validMailbox } = await emailValidator.verify(req.body.post);
res.send(
`response received , welllformed = ${wellFormed}, validDomain = ${validDomain}, validMailbox = ${validMailbox}`,
);
});
i have installed my my validator on server using npm i add deep-email-validator --save
My Directory on server has
asset-manifest.json index.html manifest.json package.json static
build logo192.png node_modules robots.txt
favicon.ico logo512.png package-lock.json server.js
Can you access other endpoints in server.js on DigitalOcean? EG: if you create:
app.get('/', function (req, res) {
res.send('hello world')
})
And make a request to it from your React app does it reach that endpoint?
I think you will struggle to run the React app and server from the same location.
If your React app is setup correctly it will try to handle all requests coming to that url.
You could run the express server on a different port to the React app. Then traffic won't get routed to both the React server and your Express server.

Combining a ExpressJS Router endpoint with a fetch call to an external enpoint

I am trying to create an Express Router endpoint that will return the CSV file from an external API (Jenkins in this case)
In more detail, what I am trying to achieve is to have a React Frontend call this route on the Express backend and download a CSV file.
BACKEND
The Express route is has this structure:
router.get('/path/latestCsvTestReport', async (req, res) => {
const { channel } = req.params;
return fetch(
`${jenkinsHost}/job/${channel}/${jenkinsPath}/lastSuccessfulBuild/artifact/test_result/report_test.csv`, {
...fetchOptions,
headers: { Authorization: jenkinsAuth},
},
)
.then(r => {
console.log('====== DATA =====', r);
res.setHeader('Content-type', 'text/csv');
res.setHeader('Cache-Control', 'no-cache');
res.send(r)
})
.catch((err) => {
// console.log(err);
res.status(404);
res.send('report not found');
});
});
and the URL called in the fetch returns a CSV file.
FRONTEND
I am calling the Express endpoint from a method on the React frontend using the following function, which utilised the file-saver library:
async function triggerReportDownload(chlId) {
console.log('===== CSV Request ====')
const resource = `/api/jenkins/${chlId}/latestCsvTestReport`;
saveAs(resource, "report.csv")
}
which is triggered by the click of a button on the FrontEnd.
At the moment, the button, triggers a download but the csv downloaded only contains:
{"size":0 timeout:0}
I am certain I am doing something completely wrong on the way the backend returns the CSV from the fetch call, but for the life of me I do not seem to be able to find the way to formulate the response. Any help/direction towards fixing this would be greatly appreciated.
The solution to this is to simply things as possible (being a newbie I had overcomplicated things). So here we are:
Backend
Import the utils library and then create a stream:
import util from 'util';
const streamPipeline = util.promisify(require('stream').pipeline);
This is then called from the Express router:
router.get('/jenkins/:channel/latestCsvTestReport.csv', async (req, res) => {
const { channel } = req.params;
const response = await fetch(
`${jenkinsHost}/job/${channel}/${jenkinsPath}/lastSuccessfulBuild/artifact/test_result/report_test.csv`, {
...fetchOptions,
headers: { Authorization: jenkinsAuth },
},
);
res.setHeader('Content-disposition', `attachment; filename=report_test_${Date.now()}.csv`);
res.set('Content-Type', 'text/csv');
return streamPipeline(response.body, res);
});
Frontend
Use windows.open to get the download file
async function triggerReportDownload(chlId) {
window.open(`/api/jenkins/${chlId}/latestCsvTestReport.csv`);
}

Resources