Problem with fsPromises.readFile used in module - javascript

I use XMLHttpRequest in Node.js and when handling request in server.js (asynchronous POST request) I use this code:
const filePath = './input.pdf';
fsPromises.readFile(filePath)
.then(res => {
const pdfBytes = new Uint8Array(res).buffer;
})
.catch(err => {
console.log('Could not read file-template');
});
then I get ArrayBuffer through this code. But I want to move this code into module and call export function there with this code. This change disrupted reading file and devtools network returns error in my request with message 'Provisional headers are shown'.
How can I make it work in module, not in server.js?
I attached images with messages in devtools img1, img2

Related

POST image to django rest API always returns 'No file was submitted'

I am trying to get this working now for days -.-
Using a simple NodeJS express server, I want to upload an image to a Django instance through Post request, but I just can't figure out, how to prepare the request and embed the file.
Later I would like to post the image, created from a canvas on the client side,
but for testing I was trying to just upload an existing image from the nodeJS server.
app.post('/images', function(req, res) {
const filename = "Download.png"; // existing local file on server
// using formData to create a multipart/form-data content-type
let formData = new FormData();
let buffer = fs.readFileSync(filename);
formData.append("data", buffer); // appending the file a buffer, alternatively could read as utf-8 string and append as text
formData.append('name', 'var name here'); // someone told me, I need to specify a name
const config = {
headers: { 'content-type': 'multipart/form-data' }
}
axios.post("http://django:8000/images/", formData, config)
.then(response => {
console.log("success!"); // never happens :(
})
.catch(error => {
console.log(error.response.data); // no file was submitted
});
});
What am I doing wrong or did I just miss something?
EDIT
I just found a nice snippet with a slighlty other approach on the npm form-data page, on the very bottom (npmjs.com/package/form-data):
const filename = "Download.png"; // existing local file on server
let formData = new FormData();
let stream = fs.createReadStream(filename);
formData.append('data', stream)
let formHeaders = formData.getHeaders()
axios.post('http://django:8000/images/', formData, {
headers: {
...formHeaders,
},
})
.then(response => {
console.log("success!"); // never happens :(
})
.catch(error => {
console.log(error.response.data); // no file was submitted
});
sadly, this doesn't change anything :( I still receive only Bad Request: No file was submitted
I don't really have much Django code just a basic setup using the rest_framework with an image model:
class Image(models.Model):
data = models.ImageField(upload_to='images/')
def __str__(self):
return "Image Resource"
which are also registered in the admin.py,
a serializer:
from .models import Image
class ImageSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Image
fields = ('id', 'data')
using automatic URL routing.
I wrote a simple test script and put the same image on the django server, to verify that image uploads works, and it does:
import requests
url = "http://127.0.0.1:8000/images/"
file = {'data': open('Download.png', 'rb')}
response = requests.post(url, files=file)
print(response.status_code) # 201
I had a similar problem: I used the same Django endpoint to upload a file using axios 1) from the client side and 2) from the server side. From the client side it worked without any problem, but from the server side, the request body was always empty.
My solution was to use the following code:
const fileBuffer = await readFile(file.filepath)
const formData = new FormData()
formData.append('file', fileBuffer, file.originalFilename)
const response = await fetch(
urlJoin(BACKEND_URL),
{
method: 'POST',
body: formData,
headers: {
...formData.getHeaders(),
},
}
)
A few relevant references that I found useful:
This blog post, even though it seems the author manages to send form data from the server side using axios, I did not manage to reproduce it on my case.
This issue report in the axio repository, where one comment suggests to use fetch.
In your node.js express server instead of adding the image to the form data, try directly sending the stream in the API post.
const filename = "Download.png"; // existing local file on server
//let formData = new FormData();
let stream = fs.createReadStream(filename);
//formData.append('data', stream)
let formHeaders = formData.getHeaders()
axios.post('http://django:8000/images/', stream, {
headers: {
...formHeaders,
},
})
.then(response => {
console.log("success!"); // never happens :(
})
.catch(error => {
console.log(error.response.data); // no file was submitted
});
I still didn't manage to get this working with axios so I tried another package for sending files as post requests, namely unirest, which worked out of the box for me.
Also it is smaller, requires less code and does everything I needed:
const filename = "Download.png"; // existing local file on server
unirest
.post(url)
.attach('data', filename) // reads directly from local file
//.attach('data', fs.createReadStream(filename)) // creates a read stream
//.attach('data', fs.readFileSync(filename)) // 400 - The submitted data was not a file. Check the encoding type on the form. -> maybe check encoding?
.then(function (response) {
console.log(response.body) // 201
})
.catch((error) => console.log(error.response.data));
If I have some spare time in the future I may look into what was wrong with my axios implementation or someone does know a solution pls let me know :D

How to read file from #google-cloud/storage?

I am retriving a file from my bucket.
I get the file and want to read it's contents but I do not want to download it to my local project
i just want to read the contents, take the data and do other operations with it.
my code:
export const fileManager = async () => {
try {
const source = 'upload/';
const options = { prefix: source, delimiter: '/' };
const remoteFile = st.bucket(bName).file('myData.csv');
const readFileData;
remoteFile
.createReadStream()
.on('error', err => {
console.log('error');
})
.on('response', response => {
readFileData = response;
console.log('success');
// Server connected and responded with the specified status and headers.
})
.on('end', () => {
console.log('end');
// The file is fully downloaded.
});
console.log("data", readFileData)
} catch (error) {
console.log('Error Is', error);
}
};
readFileData is undefined.
Is this possible? Every example I find envolves me downloading the file.
createReadStream is asynchronous and returns immediately. You have to use the callbacks to find out when the download to memory is complete. Right now, your code is always going to print "data undefined" because it's trying to print the response before it's available.
createReadStream is definitely the right way to go, but you will have to understand how node streams work in order to process the results correctly. There is a whole section in the linked documentation for reading streams, which is what you want to do here. The way you deal with the stream is not specific to Cloud Storage - it's the same for all node streams.
You might be helped by the answers to these questions that deal with reading node streams:
Node.js: How to read a stream into a buffer?
Convert stream into buffer?
How do I read the contents of a Node.js stream into a string variable?

mocked data with multiple JSON files seem to be overwrited when load at browser (vuex+axios)

I'm having an error that's blowing my mind. I'm trying to mock some data in order to test my app developed with Vuex + Axios.
So...
Having these JSON files at my project's folder:
And this AJAX method:
function fetchChartsData(platform, content) {
const url = `server/chartsCollection?platform=${platform}&content=${content}.json`;
axios
.get(url)
.then(response => (console.log(response.data)))
.catch(error => console.error('fails:', error));
}
I'm getting a JSON file with:
The correct route name
BUT The data/content from another file
For example, the file name at Network is correct:
But the content is from another file:
It's hard to explain. There is no pattern to check with which file is changing the content. I've disabled cached as well.
Thank you!
UPDATE
If I store each file at an isolated folder... it works. I mean:
Mocked server folder:
New code:
function fetchChartsData(platform, content) {
const url = `server/${platform}/chartsCollection?platform=${platform}&content=${content}.json`;
axios
.get(url)
.then(response => (console.log(response.data)))
.catch(error => console.error('fails:', error));
}
It's fine that it works... but I'd need to have all files at the same folder to simulate the real backend environment.

Node server to send image to cloud to be hosted

I send an image file to my node server via my react app -
I want to host these images on google cloud or similar so they have an accessible URL.
I have tried using cloudinary and google cloud but to no avail thus far!
My react-side code (shortened):
imageFile = this.state.files[0])
const formData = new FormData()
formData.append('file', imageFile);
sendImage(formData)
sendImage(image) {
axios.post("https://137a6167.ngrok.io/image-upload", image, {
})
.then(res => { // then print response status
console.log(res.statusText)
})
}
The file is successfully sent to my server and consoled:
app.post('/image-upload', (req, res) => {
console.log('consoling the req.body!!!!' + JSON.stringify(req.body))
})
THE CONSOLE: consoling the req.body!!!!{"1":"[object File]"}
I did try use this following cloudinary method, yet it threw errors:
cloudinary.config({
cloud_name: process.env.CLOUD_NAME,
api_key: process.env.API_KEY,
api_secret: process.env.API_SECRET
})
app.use(formData.parse())
app.post('/image-upload', (req, res) => {
const values = Object.values(req.files)
const promises = values.map(image => cloudinary.uploader.upload(image.path))
Promise
.all(promises)
.then(results => res.json(results))
})
this gave me the error that an unhandled error in the promise wasnt handled and i got a bit lost with where to go beyond that!
I looked at google cloud storage too but couldn't get it working! Any advice?
What I really want to do is return back to my react app the URL of the hosted image - so it can be stored in DB for the user!
If you can help at all that would be greatly appreciated, thank you.
There are couple of things you need to fix on the front end before you try to upload to any cloud.
First you need to set 'Content-Type': 'multipart/form-data' header in axios to send the file data properly.
Check this thread for more details: How do I set multipart in axios with react?
Then on the express side you need multer or some other similar library to receive the data. You can't access it from req.body. multer adds req.files for example.
https://github.com/expressjs/multer
Try there steps and then post the exact error message you are receiving from google cloud.

Cannot post an image to S3 using node.js aws-sdk

I'm trying to get a POST endpoint working with AWS, to post an image to an amazon bucket, but i'm getting the following error from s3fs/aws-sdk.
Unhandled rejection MalformedXML: The XML you provided was not well-formed or did not validate against our published schema
Why is this error happening and how can it be fixed?
Here is my POST function amongst other relevant things:
import fs from 'fs';
import s3fs from 's3fs';
const S3FS = s3fs;
const s3fsImp = new S3FS('testbucket', {
accessKeyId: 'asdf...',
secretAccessKey: '1234...',
});
s3fsImp.create();
...
const file = req.files.file;
const stream = fs.createReadStream(file.path);
return s3fsImp.writeFile(file.originalFileName, stream).then(() => {
fs.unlink(file.path, (err) => {
if (err) {
console.error(err);
}
res.json({ working: true });
});
});
I find the error message quite useless because i'm not providing any XML. Do I need to declare/flag a schema somewhere or something? I don't understand why this is happening yet.
I'm testing this with Postman:
no content type set
sending image via body 'file' set as type 'file' (as apposed to 'text')
plain form-data
I've been reading some documentation and tutorials and i'm now unsure how to continue with this. Any help is appreciated.

Categories