Create csv and post as multipart/form-data in JavaScript - javascript

How can I create an equivalent code in JavaScript?
Given ['col1', 'col2'] and ['val1', 'val2'] OR 'col1,col2\r\nval1,val2\r\n'
I want to be able to create a csv object without reading/writing to disk and then POST it.
Python:
from io import StringIO
import csv
import requests
f = StringIO()
w = csv.writer(f)
w.writerow(['col1', 'col2'])
w.writerow(['val1', 'val2'])
input_byte = f.getvalue().encode('UTF-8')
headers = {'Content-Type':"multipart/form-data"}
endpoint = "http://localhost:8085/predict"
files = {'file': ('input.csv', input_byte)}
response = requests.post(endpoint, files=files)
Here is my code in JavaScript so far:
let data = [['col1', 'col2'],
['val1', 'val2']];
// convert to csv format
let csvContent = data.map(e => e.join(",")).join("\r\n") + "\r\n";
// I believe FormData object is required to send multipart/form-data
// I do not think I am passing my csv data correctly
let body = new FormData();
let buff = Buffer.from(csvContent, "utf-8");
body.append("file", buff, {filename : 'input.csv'});
let response = await fetch("http://localhost:8085/predict",
{
method: 'POST',
body: body,
headers: {'Content-Type':"multipart/form-data"}
});
EDIT:
I was able to send a csv file but had to write it to a disk first. Is it possible to avoid it?
let data = [['col1', 'col2'],
['val1', 'val2']];
// convert to csv format
let csvContent = data.map(e => e.join(",")).join("\r\n") + "\r\n";
// save a csv file
let path = './files/' + Date.now() + '.csv';
fs.writeFile(path, csvContent, (err) => {
if (err) {
console.error(err);
}
});
let body = new FormData();
// this works :)
// but how can I create a csv buffer without writing to a disk?
body.append("file", fs.createReadStream(path), {filename : 'input.csv'});
let response = await fetch("http://localhost:8085/predict",
{
method: 'POST',
body: body,
});

I was able to solve my question with the following script:
const FormData = require('form-data');
const Readable = require('stream').Readable;
const fetch = require("node-fetch");
let data = [['col1', 'col2'],
['val1', 'val2']];
// convert to csv format
let csvContent = data.map(e => e.join(",")).join("\r\n") + "\r\n";
const stream = Readable.from(csvContent);
let body = new FormData();
body.append("file", stream, {filename : 'input.csv'});
let response = await fetch("http://localhost:8085/predict",
{
method: 'POST',
body: body,
});

Related

How To Upload Multiple Images In Angular

I have a code for uploading a file to an api .. then api respond with a string url..
then I use that url inside a form group object.
now in my template I need to upload many images > then get each url as a parameter then send them with a json object to api . any one know how to do this please ?
here is my component.ts
let image = product['image'];
let prodImage = new FormData();
prodImage.append('file', image);
let fileUrl = `**********************`;
return this.http.post(fileUrl, prodImage, {
headers: new HttpHeaders().set(
'Authorization',
`Bearer ${localStorage.getItem('user-jwt')}`)
}).subscribe(
(res: any) => {
console.log(res.data.url)
product.image_url = res.data.url;
this.productsService.createProduct(product).subscribe(
//sucess
(response: any) => {}
)}
there problem is when I need many images
let imageFr = let image = product['imageFr'];
let imageEn = let image = product['imageEn'];
let imageDe = let image = product['imageDe'];
let prodImageFr = new FormData();
prodImageFr.append('file', imageEn);
let prodImageEn = new FormData();
prodImageEn.append('file', imageEn);
let prodImageDe = new FormData();
prodImageDe.append('file', imageDe);
I don't wanna use many http post requests inside each others .. If there is any other clean solution..
Thanks

Send canvas.toDataURL images to nodejs

I'm trying to send image from front-end script to my server.
Front-end script:
var img_data = canvas.toDataURL('image/jpg'); // contains screenshot image
// Insert here POST request to send image to server
And I'm trying to accept the data in the backend and store it into req.files to be able to access like this:
const get_image = (req, res) => {
const File = req.files.File.tempFilePath;
}
What way can I do to send the image to the server and get the image like in the example above?
your img_data is a base 64 string, which you can send to server directly in a post request
e.g.
await fetch('/api/path', { method: 'POST', headers: { "content-type": "application/json"}, body: JSON.stringify({ file: img_data }) });
On your backend, you can convert this string to binary, and save to file.
var fs = require('fs');
app.post('/api/path', async (req, res) => {
const img = req.body.file;
var regex = /^data:.+\/(.+);base64,(.*)$/;
var matches = string.match(regex);
var ext = matches[1];
var data = matches[2];
var buffer = Buffer.from(data, 'base64'); //file buffer
.... //do whatever you want with the buffer
fs.writeFileSync('imagename.' + ext, buffer); //if you do not need to save to file, you can skip this step.
....// return res to client
})
You have to convert it to a Blob first, and then append it to a Form. The form would be the body of the request that you send to server.
canvas.toBlob(function(blob){
var form = new FormData(),
request = new XMLHttpRequest();
form.append("image", blob, "filename.png");
request.open("POST", "/upload", true);
request.send(form);
}, "image/png");

Slicing file via Javascript for upload to Dropbox API gets received into the server as incomplete/corrupt

I was wondering if anyone could take a peek at this javascript. It takes a file and slices it with a for loop and sends the sliced bits to the backend which gets sent to the Dropbox API. when they get put in the dropbox, they're missing quite a few megabytes, and dont open how they should. For example, I sent an avi file and the video is about a quarter of the length its supposed to be. If anyone has nay ideas please let me know.
for(let start = 0; start < file.size; start += chunkSize){
const slice = file.slice(start,start + chunkSize + 1)
const fd = new FormData()
fd.append('data', slice)
//count tells the server which api endpoint to hit (start sessions/append to session)
fd.append('count', start)
if(start != 0){
fd.append('session_id',sessionID)
fd.append('offset', uploadedSoFar)
}
uploadedSoFar += slice.size;
await fetch('/wp-content/plugins/Basic/chunks.php', {
method: 'POST',
body: fd
}) .then(response => response.text() )
.then((result) =>{
if(start == 0){
const json = JSON.parse(result);
sessionID = json['session_id']
console.log(sessionID)
}
console.log(result)
//finishChunk()
});
}
const fd2 = new FormData();
fd2.append('session_id', sessionID)
const filepath = window.filePath;
const filename = file.name;
fd2.append('path', `${filepath}${filename}`)
fd2.append('filesize', uploadedSoFar)
fetch('/wp-content/plugins/Basic/finishchunk.php', {
method: 'POST',
body: fd2
}) .then(response => response.text() )
.then(result=>{
console.log(result)
});
}

Download the file that's returned from the Web Api Post method React

I have an ASP.Net Web API method which is returning a zip file, which seems happening properly, now what I want is, I want to download that zip file at the client location using React. My Api method is as follows:
[HttpPost]
public FileContentResult Post([FromForm] string communityName, [FromForm] string files)
{
var removedInvalidCharsFromFileName = removeInvalidCharsFromFileName(files);
var tFiles = removedInvalidCharsFromFileName.Split(',');
string rootPath = Configuration.GetValue<string>("ROOT_PATH");
string communityPath = rootPath + "\\" + communityName;
byte[] theZipFile = null;
using (MemoryStream zipStream = new MemoryStream())
{
using (ZipArchive zip = new ZipArchive(zipStream, ZipArchiveMode.Create, true))
{
foreach (string attachment in tFiles)
{
var zipEntry = zip.CreateEntry(attachment);
using (FileStream fileStream = new FileStream(communityPath + "\\" + attachment, FileMode.Open))
using (Stream entryStream = zipEntry.Open())
{
fileStream.CopyTo(entryStream);
}
}
}
theZipFile = zipStream.ToArray();
}
return File(theZipFile, "application/zip", communityName + ".zip");
}
And my React/JS method is as follows:
handleDownload = (e) => {
e.preventDefault();
var formData = new FormData();
formData.append('communityname', this.state.selectedCommunity);
formData.append('files', JSON.stringify(this.state['checkedFiles']));
let env = 'filesApi.' + clientConfiguration['Environment'];
let url = clientConfiguration['filesApi.local'];
alert(url);
axios({
method: 'post',
url: url,
data: formData
})
.then(res => {
//console.log(res.data);
var binaryData = [];
binaryData.push(res.data);
const src = window.URL.createObjectURL(new Blob(binaryData, { type: "application/zip" }));
var fileName = `${this.state['selectedCommunity']}.zip`;
saveAs(src, fileName);
});
};
It is downloading the zip file, but says the following error when I try to unzip the file at the client location, what am I missing - not able to understand:
Can not open the file as zip archive, is not archiving, Warning Headers error
, any help please

How to send additonal data along with form data in angular

I am sending attached files/images with formData to back end along with content of the mail and then inject them into nodemailer, I am using multer as a middleware if it helps
component.ts
let fileList: FileList = event.target.files;
if(fileList.length > 0) {
this.formData = new FormData();
for(let i = 0 ; i < fileList.length; i++){
let file: File = fileList[i];
this.formData.append('uploadFile', file, file.name);
}
}
service.ts(this works and I can fetch files from req.files in the node)
sendData(formData){
let headers = new HttpHeaders();
return this.http.post('http://localhost:3000/mail',formData)
}
service.ts(doesn't work, need to do this)
sendEmail(formData,email){
let data = { data : email , formData : formData}
return this.http.post('http://localhost:3000/mail',data)
}
both req.files and req.body.formData comes undefined in this case,
I tried appending the formdata to the header but I don't know the proper way to append/fetch or maybe it's not possible to.
Node.js Part
var storage = multer.diskStorage({
destination : (req,file, callback)=>{
req.body.path = [];
callback(null, './storage');
},
filename : (req, file ,callback)=>{
let filename = Date.now() + '-' +file.originalname;
req.body.path.push(filename);
callback(null, filename);
app.post('/mail',upload.any(),nodemailer);
nodemailer.js
module.exports = (req,res)={
console.log(req.files); X
//Code Irrelevant for this question
}
For this you have to do it like this :
sendEmail(formData,email){
let headers = new HttpHeaders();
formData.append('email', email);
return this.http.post('http://localhost:3000/mail',formData);
}
Reason, you have to pass the form as multipart and you are trying to
send data as JSON , so it will not receive anything until you pass the
whole thing as above.
sendEmail(formData,email){
let data = { data : email , formData : formData}
return this.http.post('http://localhost:3000/mail',data)
}
as you can see in your function you are sending the JSON.

Categories