Uploading files to server

I want to upload files from the frontend to my server as opposed to AWS S3. I have implemented the code below in my operations.ts file which is in my module's subdirectory under /src: personita/app/src/personita/operations.ts import { fileURLToPath } from 'url' import path from 'path' // Get the current file's directory const __filename = fileURLToPath(import.meta.url) const __dirname = path.dirname(__filename) // Navigate to project root (app directory) and create uploads folder there // From: src/personita/operations.ts // Up to: src/personita/ // Up to: src/ // Up to: app/ const UPLOAD_DIR = path.join(__dirname, '..', '..', '..', 'uploads') // Log the path to verify console.log('Upload directory path:', UPLOAD_DIR) // Ensure upload directory exists if (!fs.existsSync(UPLOAD_DIR)) { fs.mkdirSync(UPLOAD_DIR, { recursive: true }) console.log('Created upload directory:', UPLOAD_DIR) } According to the code above, I expect the files to be uploaded to personita/app/uploads however they are being saved in the .wasp directory instead personita/app/.wasp/. How do I fix this?
3 Replies
kapa.ai
kapa.ai4w ago
Hi @cking!M. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- To address your issue with file uploads being saved in the .wasp directory instead of your desired personita/app/uploads directory, we need to make some adjustments to your approach. The problem likely stems from how Wasp handles file uploads and server-side operations. Here's how you can modify your setup to achieve the desired result: 1. First, you'll need to use Wasp's server setup function to configure file uploads. This can be done in your main.wasp file. 2. Then, you'll need to create a custom API route to handle the file upload. 3. Finally, you'll use Multer, a middleware for handling multipart/form-data, which is primarily used for uploading files. Here's how you can implement this: 1. In your main.wasp file, add the following:
app MyApp {
// ... other configurations
server: {
setupFn: import { serverSetup } from "@server/serverSetup.js"
},
}

api uploadFile {
fn: import { uploadFile } from "@server/uploadFile.js",
httpRoute: (POST, "/upload-file")
}
app MyApp {
// ... other configurations
server: {
setupFn: import { serverSetup } from "@server/serverSetup.js"
},
}

api uploadFile {
fn: import { uploadFile } from "@server/uploadFile.js",
httpRoute: (POST, "/upload-file")
}
2. Create a new file src/server/serverSetup.js:
import multer from "multer";
import path from "path";

const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, path.join(process.cwd(), 'uploads'));
},
filename: function (req, file, cb) {
const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9);
cb(null, file.fieldname + '-' + uniqueSuffix + path.extname(file.originalname));
}
});

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

export const serverSetup = (app) => {
app.use(upload.single('file'));
};
import multer from "multer";
import path from "path";

const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, path.join(process.cwd(), 'uploads'));
},
filename: function (req, file, cb) {
const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9);
cb(null, file.fieldname + '-' + uniqueSuffix + path.extname(file.originalname));
}
});

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

export const serverSetup = (app) => {
app.use(upload.single('file'));
};
3. Create another file src/server/uploadFile.js:
import fs from 'fs';
import path from 'path';

export const uploadFile = (req, res) => {
if (!req.file) {
return res.status(400).send('No file uploaded.');
}
const uploadDir = path.join(process.cwd(), 'uploads');
if (!fs.existsSync(uploadDir)) {
fs.mkdirSync(uploadDir, { recursive: true });
}

res.status(200).json({
message: 'File uploaded successfully',
filename: req.file.filename
});
};
import fs from 'fs';
import path from 'path';

export const uploadFile = (req, res) => {
if (!req.file) {
return res.status(400).send('No file uploaded.');
}
const uploadDir = path.join(process.cwd(), 'uploads');
if (!fs.existsSync(uploadDir)) {
fs.mkdirSync(uploadDir, { recursive: true });
}

res.status(200).json({
message: 'File uploaded successfully',
filename: req.file.filename
});
};
This setup will ensure that files are uploaded to the uploads directory in your project root (personita/app/uploads). To use this in your frontend, you can make a POST request to /upload-file with the file data. This approach is based on the Wasp documentation for custom API routes (https://wasp-lang.dev/docs/advanced/apis) and server setup (https://wasp-lang.dev/docs/project/server-config#setup-function), as well as community discussions about file uploads in Wasp projects Discord support thread (https://discord.com/channels/686873244791210014/1217681705511686194). Remember that storing files directly on the server might not be the best approach for production environments, especially if your server instances are ephemeral. For production use, consider using cloud storage solutions like AWS S3 or similar services. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ---------------------- Sorry @cking!M, 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
miho4w ago
@Vinny (@Wasp) maybe one for you
Vinny (@Wasp)
Vinny (@Wasp)4w ago
Hey @cking!M I would suggest using AWS at it's much more secure and performant. If you still prefer to save files to your own db, follow the guide from the Open SaaS docs: https://docs.opensaas.sh/guides/file-uploading/#using-multer-to-upload-files-to-your-server
OpenSaaS.sh
File Uploading
Open SaaS is a free, open-source, full-stack SaaS starter kit for React + NodeJS.
Want results from more Discord servers?
Add your server