Post File object within an array of object with Axios? - file

Are we able to upload File objs within an object with other keys? I've been asked to add an import_type key to an object, but its already a File obj when I'm upload it using a package called react-dropzone https://react-dropzone.js.org/
So I'd have to do something like
[{file: //File obj,
import_type: 1
}, {file: //File obj,
import_type: 1
},]
This is being sent in a post request
export const uploadFiles = (formData) => {
return axios.post("/upload", formData, {
headers: {
"Content-Type": "multipart/form-data",
},
});
};
I'm getting an error "Missing Data" and it is only showing this as the data sent...
data: ["file": {"path": "",} //file path
"import_type": 1 //value I want sent with the obj

Source of issue: I was passing in an entire array and axios was not looking for that but a single file.
My solution: I'm mapping through the array instead and using Promise.all for each array value so that it will be processed properly.

Related

Format to POST a file to the ImageKit server?

I've successfully built a React UI to select and upload N files. The key part of it is this:
<input type='file' accept='image/*' id='selectFiles' multiple onChange={handleFileChange} />
The selected files are stored in this state variable:
const [fileList, setFileList] = React.useState<FileList>();
I know they're correctly there because I iterate through them and show them in a preview DIV.
Following ImageKit's instructions, I successfully built an Auth endpoint which returns the auth credentials.
Then, within a useEffect I iterated through fileList to upload one photo at a time to the ImageKit server. But even trying just one file, I keep getting a 400 error informing me that the fileName parameter is missing. It definitely is not missing so I suspect that the problem lies with what I'm providing as the file parameter.
Here's the critical code (with some data obscured for privacy reasons) :
const uploadFile = async (file: File) => {
try {
const body = {
file: file,
publicKey: 'my_public_key',
signature: 'imageKit_signature',
expire: 'imageKit_expiry_value',
token: 'imageKit_token',
fileName: 'test123.jpg',
useUniqueFileName: false,
folder: userName,
overwriteFile: false,
};
const response = await axios.post('https://upload.imagekit.io/api/v1/files/upload', body);
console.log(response.status, response.data);
} catch (err) {
console.error(err);
}
};
Might anyone see what I'm doing wrong?
Robert
I solved the problem. If you're going to upload a file to ImageKit using their POST endpoint, you need to explicitly set the headers like this:
const response = await axios.post(
'https://upload.imagekit.io/api/v1/files/upload',
body,
{ headers: {'Content-Type': 'multipart/form-data'} }
);
For those wondering, here's the barebones body:
const body = {
file: base64File,
publicKey: imageKitPublicKey,
signature: authParams?.signature,
expire: authParams?.expire,
token: authParams?.token,
fileName: 'someFilename.ext',
};
But indeed, specifying Content-Type like above will allow you to upload a file to their server.

Trying to upload files to firebase storage but its not working. Error object is empty, how do I figure out what's wrong?

So i'm trying to send image files uploaded by my users to firebase storage using the file type input element. Like this:
<input
className={inputStyle}
{...register("donorPhotoFile")}
type="file"
accept=".png, .jpg,.jpeg"
></input>
So when I try to console.log the value returned of that input, im getting an object with the following properties:
name: "file_name.jpg",
size: ,
type: "image/png"
webkitRelativePath: ""
The /api/firebase is my api endpoint in next.js to upload my form data to firestore. From the firebase documentation, the 'file' should come from File API which I've did but its always unsuccessful and im not sure what im doing wrong.
const submitForm = async (data) => {
const imageFile = data.donorPhotoFile[0] //this is the file
const imageUpload = await fetch("/api/firestorage", {
method: "POST",
body: imageFile
});
const res = await imageUpload.json()
console.log(res)
}
//in my firestorage endpoint i've done this:
const storage = getStrorage(app) //app here is an instance of my firebase initialized
const handler = async (req, res) => {
const storageRef= ref(storage)
const imageFile = req.body
try {
uploadBytes(storageRef, imageFile);
res.status(200).json({statusRes: "success"})
} catch(error) {
res.status(400).json({statusRes: "failed", errorMessage: error})
}
}
Doing that returns a storage/invalid-root-operation error code with a message of:
"Firebase Storage: The operation 'uploadBytes' cannot be performed on a root reference, create a non-root reference using child, such as .child('file.png')
So tried to make a reference to a specific file and inserted the file name as a second parameter to storageRef like this:
const storageRef = ref(storage).child(`images/${req.body.name}`)
but its still not working but now i'm getting an empty error object so I can't figure out what's wrong now. So i actually tried checking what req.body is and it's returning this:
file object in my api endpoint
I don't understand why is it like that? And what im actually looking at? What i've sent in my post request is a File object. Like this:
File object i attached to my post request
You can create a reference to a path using Modular SDK as shown below:
const storageRef= ref(storage, `images/${req.body.name}`)
The .child() method is used in older name-spaced syntax.

unable to post with file upload using axios react js

I am trying to post multi-part form data with file upload using React and Axios. I tried the same in Postman and this is working correctly. But in react, I get "Required request part 'file' is not present". My code:
const selectedFile = event.target.file.files[0].name;
const formData = new FormData();
formData.append('name',this.state.name);
formData.append('description',this.state.description);
formData.append('file', selectedFile);
// Here I am passing content type and token and Post request .
axios({
method: 'post',
url: 'http://localhost:8080/user/1/savecategory',
data: formData,
headers: {
'Authorization':`Bearer ${passToken}`,
'Content-Type':'multipart/form-data'
}
})
.then(
(response) => {
alert("Category Saved..!");
},
(error) => {
console.log(error);
alert("Failed..!");
}
);
You haven't add the file field to the FormData Object. you only passed the name of the file as the second parameter.
de definition of append method is like this
For regular form field
formData.append(name, value);
And for Field field you can add It using this syntax
formData.append(name, value, filename);
Here selectedFile contain the name of the file which is selected in the file input field
const selectedFile = event.target.file.files[0].name;
When you call formData.append('file', selectedFile); you are passing the name of the file as value of the form element with name file and not the file It self.
to pass the file It self you should perform It like this
const selectedFile = event.target.file.files[0];
After that you can call formData.append('file', selectedFile);
Learn more about FormData.append

How to add additional request body values to Apollo GraphQL request?

I'm using Apollo with the Scaphold.io service and for writing blobs to that service I need to be able to add additional options to the request body.
The full Scaphold example can be found here: https://scaphold.io/docs/#uploading-files
But it does something like this:
form.append("variables", JSON.stringify({
"input": {
"name": "Mark Zuck Profile Picture",
"userId": "VXNlcjoxMA==",
"blobFieldName": "myBlobField"
}
}));
// The file's key matches the value of the field `blobFieldName` in the variables
form.append("myBlobField", fs.createReadStream('./mark-zuckerberg.jpg'));
fetch("https://us-west-2.api.scaphold.io/graphql/scaphold-graphql", {
method: 'POST',
body: form
}).then(function(res) {
return res.text();
}).then(function(body) {
console.log(body);
});
Where it adds a blobField to the request body.
Based on this, I need to pass into the variables a blobFieldName property, and then add to the request body the value passed to that property with the blob. However, using Apollo I can't add to the request body. I tried the following, but it's absent from the request body when I check in the network inspector:
export const withCreateCoverPhoto = graphql(CreateCoverPhoto, {
props: ({mutate}) => ({
createCoverPhoto: (name, file) => mutate({
variables: {
input: {
blobFieldName: name,
},
},
[name]: file
}),
}),
});
Please advise.
Thanks for the question. Currently the best way to upload files is by [appending it to FormData and sending it up to the server using fetch] (https://medium.com/#danielbuechele/file-uploads-with-graphql-and-apollo-5502bbf3941e). Basically, you won't be able to have caching here for the file itself, but this is the best way to handle uploading files on Scaphold using a multipart request.

React dropzone, how to upload image?

Using React dropzone, I've successfully accessed the image using the onDrop callback. However, I'm trying to upload to Amazon S3 by sending the image to my server, saving to an S3 bucket, and returning a signed url to the image back to the client.
I can't do this with the information I have so far and the docs don't seem to mention this to my knowledge.
onDrop triggers a function call in my redux actions with the files:
export function saveImageToS3 (files, user) {
file = files[0]
// file.name -> filename.png
// file -> the entire file object
// filepreview -> blob:http:localhost:3000/1ds3-sdfw2-23as2
return {
[CALL_API] : {
method:'post',
path: '/api/image',
successType: A.SAVE_IMAGE,
body: {
name: file.name,
file: file,
preview: file.preview,
username: user
}
}
}
}
However, when I get to my server, I'm not sure how to save this blob image (that's only referenced from the browser.)
server.post('/api/image', (req, res) => {
// req.body.preview --> blob:http://localhost:3000/1ds3-sdfw2-23as2
// req.body.file -> {preview:blob:http://localhost:3000/1ds3-sdfw2-23as2}, no other properties for some reason
})
React Dropzone returns an array of File objects which can be sent to a server with a multi-part request. Depend on the library you use it can be done differently.
Using Fetch API it looks as follows:
var formData = new FormData();
formData.append('file', files[0]);
fetch('http://server.com/api/upload', {
method: 'POST',
body: formData
})
Using Superagent you would do something like:
var req = request.post('/api/upload');
req.attach(file.name, files[0]);
req.end(callback);

Resources