W
Wasp-lang•5w ago
Kynetix

File is not defined

My OpenSaas application has a file upload feature where you upload a file and send it to the nodejs backend (as a File object) to read the content, etc. It works fine on my macbook (wasp start), but once published to Railway, when I upload the file, I get the "ReferenceError: File is not defined" error. The line causing the error is "const reconstructedFile = new File([fileBase64], metadata.fileName, { type: metadata.fileType })" I know that nodeJS doesn't understand the File object, but why does it work when I run it locally (via wasp start), but not on the Railway server? Aren't they both nodeJS environments?
15 Replies
kapa.ai
kapa.ai•5w ago
Hi @Kynetix. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- To answer your question, I need to clarify a few points and provide some context based on the information available: 1. The File object is indeed not natively available in Node.js environments. It's a Web API that's typically available in browser environments. 2. The fact that it works locally with wasp start but not on Railway suggests there might be differences in how the environments are set up or how the code is being executed. 3. When you run wasp start locally, it's possible that the File object is being made available through a polyfill or some other mechanism that Wasp is providing in development mode. 4. On Railway, which is likely running a production build, this polyfill or mechanism might not be present, leading to the "File is not defined" error. To address this issue, you have a few options: 1. Use a File polyfill for Node.js environments. There are packages available that provide File-like functionality in Node.js, such as node-file or file-api. 2. Instead of using the File constructor, you could create a custom object with the necessary properties and methods to mimic a File object. 3. Modify your server-side code to work with the raw file data instead of trying to reconstruct a File object. For file uploads in Wasp, you might want to consider using a middleware like Multer, which is commonly used for handling multipart/form-data in Node.js. Here's an example of how you can set up file uploads using Multer in Wasp, based on a gist shared by a Wasp team member:
import multer from "multer";
import path from "path";
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, "/tmp/tp-uploads");
},
filename: function (req, file, cb) {
const originalName = path.parse(file.originalname).name;
const extension = path.parse(file.originalname).ext;
const timestamp = Date.now();
const newFilename = `${originalName}_${timestamp}${extension}`;
cb(null, newFilename);
},
});

const upload = multer({ storage: storage });

export const addMiddleware = (config) => {
config.set("multer", upload.single("file"));
return config;
};

export const uploadFile = (req, res, context) => {
console.log(req.body);
console.log(req.file);
const file = req.file;
return res.json({
fileExists: !!file,
});
};
import multer from "multer";
import path from "path";
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, "/tmp/tp-uploads");
},
filename: function (req, file, cb) {
const originalName = path.parse(file.originalname).name;
const extension = path.parse(file.originalname).ext;
const timestamp = Date.now();
const newFilename = `${originalName}_${timestamp}${extension}`;
cb(null, newFilename);
},
});

const upload = multer({ storage: storage });

export const addMiddleware = (config) => {
config.set("multer", upload.single("file"));
return config;
};

export const uploadFile = (req, res, context) => {
console.log(req.body);
console.log(req.file);
const file = req.file;
return res.json({
fileExists: !!file,
});
};
This approach avoids the need to reconstruct a File object on the server-side and should work consistently across different environments. Source: Discord support thread (https://discord.com/channels/686873244791210014/1217681705511686194) Remember to adjust your client-side code accordingly to send the file data in a format compatible with Multer (typically as form-data). If you need more specific guidance, please provide more details about your current implementation, including relevant parts of your client-side and server-side code. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ---------------------- Sorry @Kynetix, I seem to be having a bit of trouble. Don't worry though, I've pinged my support and they will try to fix me up! :technologist: Perhaps try again in 15mins?
miho
miho•5w ago
@Vinny (@Wasp) one for you
Vinny (@Wasp)
Vinny (@Wasp)•5w ago
So you're calling that function, new File() on the backend? If so, try what Kapa suggested:
Use a File polyfill for Node.js environments. There are packages available that provide File-like functionality in Node.js, such as node-file or file-api.
Kynetix
KynetixOP•5w ago
Thanks @Vinny (@Wasp), I'll give it a shot. Meanwhile, do you have a better way to implement it? The application is a document chatbot where the user uploads a file (Word doc, PDF, XLS, etc) and its content is read and stored in Supabase vector store. By the way, importing formdata-node solved the File issue.
Vinny (@Wasp)
Vinny (@Wasp)•5w ago
ok cool, so that was the issue how did you find out about the formdata-node library?
martinsos
martinsos•4w ago
Hm but why would that work locally and not once built? @Kynetix what is our node version taht you use when developing locally? Might be that it is different from the version in Docker that we produce. But still, I doubt File is a new thing hah. @miho how is it possible that in development we have File availble, but not once deployed to Railway? Coudl taht be connected to bundling we do on the backend in any way?
Kynetix
KynetixOP•4w ago
Following Kapa's suggestion, I googled "node-file" and came across "formdata-node" with some sample code, so I tried it and it worked. I use node v20.11.1.
martinsos
martinsos•4w ago
Ok, a bit of googling tells me that File was actually added in Node 20! So you used node 20 locally, and our Docker that we produce uses Node 18. So one solution is what you did, importing formdata-node, and another solution is to use node 20 in the generated Docker image.
Kynetix
KynetixOP•4w ago
Ah, interesting. So do you plan to implement node 20+ in a future version? (Speaking of, when's the next OpenSaas version coming out? 🙂 )
miho
miho•4w ago
Since Node.js 20 is the current LTS, we might as well bump Node.js in our Dockerfile 🙂
martinsos
martinsos•4w ago
Yup, that is one thing we can do, and then there is also this: https://github.com/wasp-lang/wasp/issues/1593 -> this would ensure that user specifies node version they want, and then that same version would be used in Dockerfile also. There are also couple of other places (some deps) where it is important.
miho
miho•4w ago
I'll probably tackle this one first: https://github.com/wasp-lang/wasp/issues/1778 If you want, you can jump on the one you linked, I don't think they exclude each other 🙂
martinsos
martinsos•4w ago
Yeah, they are not really conneted
Kynetix
KynetixOP•4w ago
I'm guessing you guys are the developers of Wasp? Great job guys!!
martinsos
martinsos•4w ago
Yup that is us, you can see by the yellow names (Wasp Team discord role). Thanks a lot :)!!
Want results from more Discord servers?
Add your server