Passing file to server action for upload?
Answered
American Shorthair posted this in #help-forum
American ShorthairOP
I'm having an issue figuring out if it's possible to pass an image to a server action for upload to database. If possible, id like to do this server side to avoid loading the firebase packages client side but I keep getting this error
Here is my server action attempt
handle drop from mui file drop component
Application error: a client-side exception has occurred (see the browser console for more information).
react-dom.development.js:7749 Uncaught Error: Only plain objects, and a few built-ins, can be passed to Server Actions. Classes or null prototypes are not supported.
at Array.resolveToJSON (react-server-dom-webpack-client.browser.development.js:732:31)
Here is my server action attempt
'use server';
import { storage } from './firebase';
import { ref, uploadBytes, getDownloadURL } from 'firebase/storage';
export async function uploadFileToFirebase(file, path) {
const storageRef = ref(storage, `${path}`);
try {
const snapshot = await uploadBytes(storageRef, file);
const downloadURL = await getDownloadURL(snapshot.ref);
console.log('File uploaded!', downloadURL);
return downloadURL;
} catch (error) {
console.error('Error uploading file:', error);
throw error;
}
}
handle drop from mui file drop component
const handleDrop = useCallback(
async (acceptedFiles) => {
const file = acceptedFiles[0];
if (!file) return;
try {
const downloadURL = await uploadFileToFirebase(
file,
`blog/${currentPost.urlTitle}/cover-image`
);
const newFile = {
...file,
preview: downloadURL,
};
} catch (error) {
}
},
[setValue, currentPost.urlTitle]
);
Answered by American Shorthair
So this is what I ended up doing. it works but I would not assume it's a good or secure way to do it i'm far from good at this stuff. I do beleive server action file sending has a size limitation. Not sure what it is though.
This is my handleDrop for my mui image drop handling.
And then here is my server action handling the file upload
This is my handleDrop for my mui image drop handling.
const handleDropMulti = useCallback(
(acceptedFiles) => {
setUploadingImages(true); // Indicate uploading
const uploadPromises = acceptedFiles.map((file) => {
const formData = new FormData();
formData.append('file', file);
formData.append('urlTitle', currentPost.urlTitle);
return firebaseUploadBlogMultiImage(formData);
});
Promise.all(uploadPromises)
.then((imageDataArray) => {
setImages(imageDataArray); // Directly set state with image data from server action
setUploadingImages(false);
})
.catch((error) => {
console.error('Error uploading files:', error);
});
},
[currentPost.urlTitle, setImages, setUploadingImages]
);
And then here is my server action handling the file upload
export async function firebaseUploadBlogMultiImage(formData) {
const file = formData.get('file');
const urlTitle = formData.get('urlTitle');
const path = `${urlTitle}/blog-content/${file.name}`;
const storageRef = ref(storage, path);
try {
const snapshot = await uploadBytes(storageRef, file);
const downloadURL = await getDownloadURL(snapshot.ref);
const imageData = {
name: file.name,
size: file.size,
preview: downloadURL, // Add this line
// ...other properties if needed
};
return imageData;
} catch (error) {
console.error('Error uploading image:', error);
throw error; // Rethrow the error for caller to handle
}
}
4 Replies
American ShorthairOP
So I was able to finally get it to work by passing the file in with all the form data then accessing the file that way. Not sure if there is a better way, but this is the only way i could find to get it work. still open to hearing a better way if anybody has it. Thank you
Eastern Phoebe
@American Shorthair Hi JinMa, im currently facing the same issue could you please share your final code with me?
American ShorthairOP
So this is what I ended up doing. it works but I would not assume it's a good or secure way to do it i'm far from good at this stuff. I do beleive server action file sending has a size limitation. Not sure what it is though.
This is my handleDrop for my mui image drop handling.
And then here is my server action handling the file upload
This is my handleDrop for my mui image drop handling.
const handleDropMulti = useCallback(
(acceptedFiles) => {
setUploadingImages(true); // Indicate uploading
const uploadPromises = acceptedFiles.map((file) => {
const formData = new FormData();
formData.append('file', file);
formData.append('urlTitle', currentPost.urlTitle);
return firebaseUploadBlogMultiImage(formData);
});
Promise.all(uploadPromises)
.then((imageDataArray) => {
setImages(imageDataArray); // Directly set state with image data from server action
setUploadingImages(false);
})
.catch((error) => {
console.error('Error uploading files:', error);
});
},
[currentPost.urlTitle, setImages, setUploadingImages]
);
And then here is my server action handling the file upload
export async function firebaseUploadBlogMultiImage(formData) {
const file = formData.get('file');
const urlTitle = formData.get('urlTitle');
const path = `${urlTitle}/blog-content/${file.name}`;
const storageRef = ref(storage, path);
try {
const snapshot = await uploadBytes(storageRef, file);
const downloadURL = await getDownloadURL(snapshot.ref);
const imageData = {
name: file.name,
size: file.size,
preview: downloadURL, // Add this line
// ...other properties if needed
};
return imageData;
} catch (error) {
console.error('Error uploading image:', error);
throw error; // Rethrow the error for caller to handle
}
}
Answer
@Eastern Phoebe <@181166471823491072> Hi JinMa, im currently facing the same issue could you please share your final code with me?
American ShorthairOP
Oh forgot to tag