I have a post method
uploadFile: async function () {
const formData = new FormData();
formData.append("file", this.file);
let url = `http://...`;
try {
this.source = axios.CancelToken.source();
const res = await axios.post(url, formData, {
headers: {
Authorization: "Token " + this.$store.getters.getToken,
"Content-Type": "multipart/form-data",
},
cancelToken: this.source.token,
});
} catch (error) {
}
}
and cancel method
cancelLoad: function () {
this.source.cancel('cancel upload');
},
The request was canceled, but after reloading my page, the file uploaded.
I've fixed it.
const CancelToken = axios.CancelToken;
let cancel;
const res = await axios.post(url, formData, {
headers: {...},
cancelToken: new CancelToken(function executor(c) {
cancel = c;
}),
}...
cancel();
Related
TDLR: Using s3 presigned post url to upload file to s3. Works fine on the browser but fails on the server.
I have a simple lambda function that generates presigned post url that can be consumed either in the browser or in the server.
During testing I noticed that the upload works fine one the browser but fails if I try to upload a file from a server even tho the code is identical.
The error i get is:
You must provide the Content-Length HTTP header
Detailed error:
<?xml version="1.0" encoding="UTF-8"?>
<Error>
<Code>MissingContentLength</Code>
<Message>You must provide the Content-Length HTTP header.</Message>
<RequestId>JP75YMFARK0G3X5Z</RequestId>
<HostId>toHsKmxmVYYAtac94cQoy8wXoregKG3PNBm97c3gQewEmKxLggcumTAP882T/pJNWx/lxRgH98A=</HostId>
</Error>
Request failed with status code 411
I checked online and found many threads about this issue but unfortunately not a single suggestion helped me.
Code I am running in the server
const axios = require('axios');
const { createReadStream, readFileSync } = require('fs');
const FormData = require('form-data');
const getPostPresignedUrl = async () => {
var config = {
method: 'post',
url: LAMBDA_GET_URL,
headers: {
'Content-Type': 'application/json',
},
data: JSON.stringify({
key: 'test-2.jpg',
fileType: 'image/jpeg',
}),
};
const {
data: { data },
} = await axios(config);
return data;
};
const uploadFileToS3 = async (fields, url) => {
const formData = new FormData();
Object.entries(fields).map(([key, value]) => {
formData.append(key, value);
});
const file = createReadStream('./test-1.jpg');
formData.append('file', file);
try {
const { data } = await axios({
url,
method: 'post',
headers: {
'Content-Type': 'multipart/form-data',
},
data: formData,
});
} catch (error) {
if (error instanceof axios.AxiosError) {
console.log(error.response.data);
}
console.log(error.message);
}
};
const init = async () => {
const { fields, url } = await getPostPresignedUrl();
await uploadFileToS3(fields, url);
};
init();
Code I am running in the browser:
const form = document.getElementById('form');
const input = document.getElementById('file');
const getPostPresignedUrl = async (name) => {
var config = {
method: 'post',
url: LAMBDA_GET_URL,
headers: {
'Content-Type': 'application/json',
},
data: JSON.stringify({
key: name,
fileType: 'image/jpeg',
}),
};
const {
data: { data },
} = await axios(config);
return data;
};
const uploadFileToS3 = async (fields, url, file) => {
const formData = new FormData();
Object.entries(fields).map(([key, value]) => {
formData.append(key, value);
});
formData.append('file', file);
try {
const { data } = await axios({
url,
method: 'post',
headers: {
'Content-Type': 'multipart/form-data',
},
data: formData,
});
} catch (error) {
if (error instanceof axios.AxiosError) {
console.log(error.response.data);
}
console.log(error.message);
}
};
const handleSubmit = async (e) => {
e.preventDefault();
const file = input.files[0];
const data = await getPostPresignedUrl(file.name);
await uploadFileToS3(data.fields, data.url, file);
};
form.onsubmit = handleSubmit;
This issue only occurs with posts with multipart video, Posts with images and videos below 4MB are working, when posting to Posts API i get a response with Status OK and the post URN in the header but when i try getting the post data using the given URN i'm getting error 404.
Here is the function that i am using to upload the video to LinkedIn.
const uploadVideo = async (linkedinId, accessToken, videoUrl) => {
/* Fetching video from Google storage */
const videoData = await axios.get(videoUrl, { responseType: 'arraybuffer' });
const contentType = videoData.headers['content-type'];
const videoSize = videoData.headers['content-length'];
const url = 'https://api.linkedin.com/rest/videos';
const body = {
initializeUploadRequest: {
owner: `urn:li:organization:${linkedinId}`,
fileSizeBytes: Number(videoSize),
},
};
const headers = {
Authorization: `Bearer ${accessToken}`,
'X-Restli-Protocol-Version': '2.0.0',
'x-li-format': 'json',
'LinkedIn-Version': 202207,
};
const response = await axios.post(url, body, { headers, params: { action: 'initializeUpload' } });
const { uploadInstructions } = response.data.value;
const asset = response.data.value.video;
/* Uploading video */
try {
const uploadPromises = uploadInstructions.map(async ({ uploadUrl, firstByte, lastByte }) => {
const arrayBuffer = videoData.data.slice(firstByte, lastByte);
return axios({
url: uploadUrl,
method: 'POST',
data: arrayBuffer,
headers: {
'Content-Type': contentType,
},
maxBodyLength: Infinity,
maxContentLength: Infinity,
});
});
const uploadResponses = await Promise.all(uploadPromises);
const finalizeUploadBody = {
finalizeUploadRequest: {
video: asset,
uploadToken: '',
uploadedPartIds: uploadResponses.map((uploadResponse) => uploadResponse.headers.etag),
},
};
await axios.post(url, finalizeUploadBody, {
headers: {
...headers,
'Content-Type': 'application/json',
},
params: {
action: 'finalizeUpload',
},
});
} catch (error) {
throw error;
}
return asset;
};
Here is the function that i am using to publish the post to LinkedIn.
const publishContent = async (
linkedinId,
accessToken,
media,
) => {
const url = 'https://api.linkedin.com/rest/posts';
const body = {
author: `urn:li:organization:${linkedinId}`,
commentary: 'content',
visibility: 'PUBLIC',
lifecycleState: 'PUBLISHED',
distribution: {
feedDistribution: 'MAIN_FEED',
},
};
const asset = await uploadVideo(linkedinId, accessToken, media.urls[0], isPage);
body.content = {
media: {
title: 'Title',
id: asset,
},
};
const headers = {
Authorization: 'Bearer ' + accessToken,
'X-Restli-Protocol-Version': '2.0.0',
'x-li-format': 'json',
'LinkedIn-Version': 202207,
};
return axios.post(url, body, { headers });
};
I m trying to GET response using fetch API not stuck in a error as I mentioned below. Here's my code
const DefaultLayout = () => {
let history = useHistory()
const callHomePage = async () => {
try {
const res = fetch('http://localhost:4000/api/authenticate', {
method: 'GET',
headers: {
Accept: 'application/json',
'Content-type': 'application/json',
},
credentials: 'include',
})
console.log(res)
const data = await res.json()
console.log(data)
if (!res.status === 200) {
const error = new Error(res.error)
throw error
}
} catch (err) {
console.log(err)
history.push('login')
}
}
Error: TypeError: res.json is not a function
Promise {} shows pending
const DefaultLayout = () => {
let history = useHistory()
const callHomePage = async () => {
try {
const res = await fetch('http://localhost:4000/api/authenticate', {
method: 'GET',
headers: {
Accept: 'application/json',
'Content-type': 'application/json',
},
credentials: 'include',
})
console.log(res)
const data = await res.json()
console.log(data)
if (!res.status === 200) {
const error = new Error(res.error)
throw error
}
} catch (err) {
console.log(err)
history.push('login')
}
}
You need to await the fetch statement and then call the .json method of the response.
const res = await fetch(...)
data = await res.json();
Read more: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch
I'm send a post request and I get the response like this
" [Symbol(Response internals)]: {
url: 'https://login.somenewloginpage'}"
and what I want to do is I want to open a new page via that url but it does not direct to the new page.
const login= () => async () => {
const api = `somePostRequest`
fetch(api, {
method: 'post',
headers: {
'Content-Type': 'application/x-www-form-url-encoded',
Accept: 'application/json',
},
})
.then(function(res) {
return res //maybe I should do something in this part...
})
.then(data => console.log(data));
};
Here's how to use fetch() with async/await syntax :
const login= () => async () => {
const api = `somePostRequest`;
const response = await fetch(api, {
method: 'post',
headers: {
'Content-Type': 'application/x-www-form-url-encoded',
Accept: 'application/json',
},
});
const data = await response.json(); // { url: 'https://login.somenewloginpage'}
window.location.replace(data.url); // <-- Redirection
};
I'm building an App using reactjs and I'm questioning axios.
I have an axios.post
and following that I call a function
this.props.onChangeStep1()
with the way it is written...am I safe ?
Will this.props.onChangeStep1() always wait for res.data to be full ?
onChangeHandler = event => {
console.log(event.target.files[0]);
this.setState(
{
selectedFile: event.target.files[0],
fileName: event.target.files[0].name,
loaded: 0
},
() => {
console.log(this.state.selectedFile);
console.log(this.state.loaded);
const formData = new FormData();
formData.append("file", this.state.selectedFile);
axios
.post(`/upload`, formData, {
headers: {
"Content-Type": "multipart/form-data"
}
})
.then(res => {
console.log(res);
console.log(res.data);
});
this.props.onChangeStep1(); //<---- Will this wait for res.data ?
}
);
No. It won't wait. You should put it into .then:
onChangeHandler = event => {
console.log(event.target.files[0]);
this.setState(
{
selectedFile: event.target.files[0],
fileName: event.target.files[0].name,
loaded: 0
},
() => {
console.log(this.state.selectedFile);
console.log(this.state.loaded);
const formData = new FormData();
formData.append("file", this.state.selectedFile);
axios
.post(`/upload`, formData, {
headers: {
"Content-Type": "multipart/form-data"
}
})
.then(res => {
console.log(res);
console.log(res.data);
this.props.onChangeStep1();
});
}
In your example onChangeStep will be executed before the result from axios.
You can call this.props.onChangeStep1() inside .then() block:
axios
.post(`/upload`, formData, {
headers: {
"Content-Type": "multipart/form-data"
}
})
.then(res => {
console.log(res);
console.log(res.data);
this.props.onChangeStep1();
});
Or you can use async/await
postData = async () => {
const formData = new FormData();
formData.append("file", this.state.selectedFile);
try {
const result = await axios.post(`/upload`, formData, /* all your headers..*/)
this.props.onChangeStep1(); // this line will be executed after post request
} catch(error){
// do something with error.
}
}
}
onChangeHandler = event => {
this.setState(
{
selectedFile: event.target.files[0],
fileName: event.target.files[0].name,
loaded: 0
},
this.postData)
}