VueJS Axios onUploadProgress inside the component from service - vue.js

I am trying to create a progress bar in vuejs ... however, all the tutorials are calling directly axios inside the component... my setup is a bit more ... different :)
what I have in component is this upload method
uploadPhotos() {
const formData = new FormData();
this.gallery_photos.forEach(photo => {
formData.append(`photo_${photo.name}`, photo);
});
PhotoService.uploadPhotos(this.gallery.id_gallery, formData, callback => {
console.log(callback);
})
.then(() => {
console.log("OK");
})
.catch(error => {
console.log(error);
});
}
and this is my service
uploadPhotos(id, photos) {
const config = {
onUploadProgress: function (progressEvent) {
const percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total);
console.log(percentCompleted);
}
};
return axios.post(`galleries/${id}/photos`, photos, { headers: authHeader() }, config);
}
However, from neither of those I am getting the input ... what am I missing? :(
Everything else is working fine... I am getting the files on the server side so I can process them correctly.. I just have no idea what the onUploadProgress is not doing anything

Might need to combine the headers into the config
uploadPhotos(id, photos) {
const config = {
onUploadProgress: function (progressEvent) {
const percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total);
console.log(percentCompleted);
},
headers: authHeader()
};
return axios.post(`galleries/${id}/photos`, photos, config);
}

You need to add a callback parameter to your function and trigger it:
uploadPhotos(id, photos, cb) {
const config = {
onUploadProgress: function (progressEvent) {
const percentCompleted = Math.round(
(progressEvent.loaded * 100) / progressEvent.total
);
cb(percentCompleted); // <== you can pass here whatever you want
},
};
return axios.post(
`galleries/${id}/photos`,
photos,
{ headers: authHeader() },
config
);
}
Now you will see your data:
PhotoService.uploadPhotos(this.gallery.id_gallery, formData, percent => {
console.log(percent);
})

Related

is there anything more needed than chunkUploads at true to make chunk upload work?

we want to make the chunk upload work, we are in a vuejs project and we use this version of filepond : "^4.30.4".
this how we implemented the filepond
<FilePond
v-show="!isNewVersionButton"
ref="filePondInstance"
:server="filePondServerConfig"
:label-idle="dropLabel"
:allow-multiple="true"
:accepted-file-types="acceptedFileType"
:files="[]"
:chunk-uploads="true"
:chunk-force="true"
#removefile="handleRemoveFile"
#initfile="handleInitFile"
#processfile="handleAddFile"
/>
and inside server we have this
const filePondServerConfig = {
process: async (
fieldName,
file,
metadata,
load,
error,
progress,
transfer,
options
) => {
try {
const formData = new FormData();
const signedData = await fetchSignedUrl(
file.name,
file.type,
videoId,
props.edit.productionTaskId,
props.deliverableType
);
Object.keys(signedData.data.signature).forEach((key) =>
formData.append(key, signedData.data.signature[key])
);
formData.append("file", file);
const cancelToken = axios.CancelToken.source();
const config = {
headers: {
"Upload-Length": file.size,
"Upload-Name": file.name,
"Upload-Offset": file.offset,
},
onUploadProgress: (progressEvent) => {
percentCompleted.value = Math.round(
(progressEvent.loaded * 100) / progressEvent.total
);
return progress(
progressEvent.lengthComputable,
progressEvent.loaded,
progressEvent.total
);
},
cancelToken: cancelToken.token,
};
const request = await axios.post(
signedData.data.postEndpoint,
formData,
config
);
load();
} catch (err) {
error();
}
},
};
Thank you :)
We tried to add headers in several places, but it didn't workout, what have we missed here ?
We expected headers accompanied by the request, and also the PATCH request.

Make a get request until a response comes from a request post vue js

I should upload file in my vue.js app. When I browse a file, I make post request and until I get a response, I need to make get request every 2 seconds for example. How can I do this?
uploadFile(event) {
this.isLoadingProcess = true;
console.log(this.isLoadingProcess);
let data = new FormData();
this.file = event.target.files[0];
data.append('name', 'uploaded-file');
data.append('file', event.target.files[0]);
const options = {
headers: {
'Content-Type': event.target.files[0].type,
},
onUploadProgress: function (progressEvent) {
const {loaded, total} = progressEvent;
let percentCompleted = Math.floor((loaded * 100) / total);
//console.log(percentCompleted);
if (percentCompleted !== 100) {
axios.get(url, {data: progressId})
.then(response => {
this.progress = response.data.progress;
// console.log(this.progress);
console.log(response.data.progress);
})
}
},
};
axios.post(
url,
data,
options
)
.then(response => {
console.log(response);
})
.finally(()=> {
this.isLoadingProcess = false;
})
what about this?
It asks api about update more than every 2 seconds, but It's better for my opinion in case, when endpoint isn't available
var processTimeoutFunction = null;
function checkProgress() {
axios.get('ckeck-process', ...).then(response => {
if (response.processIsActive) {
processTimeoutFunction = setTimeout(() => checkProgress(), 2000);
} else {
clearTimeout(processTimeoutFunction);
this.isLoadingProcess = false;
})
}

How to set authorization header coorectly?

Problem:
In my react native app in order to remove repeated calls I have developed a general POST GET methods in httpClient file. It code is look likes this.
import axios from 'axios';
import AsyncStorage from '#react-native-community/async-storage';
axios.defaults.headers.post['Content-Type'] = 'application/json';
var instance = null;
const setAuthorisationHeder = async () => {
const token = JSON.parse(await AsyncStorage.getItem('auth_data'));
if (token) {
console.log('>>>>>> instance', instance);
Object.assign(instance.headers, {
Authorization: 'Bearer' + token.accessToken,
});
} else {
console.log('>>>>>> instance', instance);
Object.assign(instance.headers, {
Authorization: '',
});
}
};
export const setHeader = () => {
console.log('>>>>>>>> HIIII');
instance = axios.create({
baseURL: '',
timeout: 150000,
headers: {
'Content-Type': 'application/json',
},
});
instance.interceptors.response.use(
function (response) {
return response;
},
async function (error) {
if (error.response.status) {
if (error.response.status === 401) {
AsyncStorage.removeItem('auth_data');
} else {
throw error;
}
} else {
console.log(error);
}
},
);
};
export const Get = (route, data) => {
function getData() {
return instance.get(
route,
data == null ? {data: {}} : {data: JSON.stringify(data)},
);
}
if (instance) {
console.log('>>>>>> HIIIIii');
// setAuthorisationHeder();
return getData();
}
return setHeader().then(getData);
};
export const Post = (route, data) => {
console.log('>>>>>> route', route);
function postData() {
return instance.post(route, JSON.stringify(data));
}
if (instance) {
console.log('>>>>>> HIIIIii');
// setAuthorisationHeder();
// setAuthorisationHeder();
return postData();
}
return setHeader().then(postData);
};
Can some tell me a way to add an authorization header to this instance? My token is storing the Asyncstorage in the middle of some actions so at the beginning called I don't have the token. As my code setHeader is running only one time so I created a method call setAuthorisationHeder() function. But it is giving me can not find property .then error when I am putting a request. Can someone help me to solve this issue? Thank you?
you can define global headers once and use it in every network call.
https://github.com/axios/axios#global-axios-defaults
Create a global auth variable where you'll store the auth data from storage. Before making a request get the auth data and use interceptor to set the bearer token.
let authToken = '';
const getAuthToken = async () => {
// asumming auth token was saved as string
authToken = await AsyncStorage.getItem('auth_data');
};
Interceptor
// request interceptor
axiosInstance.interceptors.request.use(
function (config) {
// Do something before request is sent
config.headers.Authorization = `Bearer ${authToken}`;
return config;
},
function (error) {
// Do something with request error
return Promise.reject(error);
}
);
complete code
import axios from 'axios';
import AsyncStorage from '#react-native-community/async-storage';
let authToken = '';
const axiosInstance = axios.create({
baseURL: '',
timeout: 150000,
headers: {
'Content-Type': 'application/json',
},
});
// request interceptor
axiosInstance.interceptors.request.use(
function (config) {
// Do something before request is sent
config.headers.Authorization = `Bearer ${authToken}`;
return config;
},
function (error) {
// Do something with request error
return Promise.reject(error);
}
);
const getAuthToken = async () => {
// asumming auth token was saved as string
authToken = await AsyncStorage.getItem('auth_data');
};
export const Get = async (route, data = {}) => {
// get and set auth token
await getAuthToken();
// route = /user?id=787878 or /user/787878
return await axiosInstance.get(route);
};
export const Post = async (route, data = {}) => {
await getAuthToken();
return await axiosInstance.post(route, data);
};

Multiple API providers with nuxt-axios and a plugin for default headers

I have a Nuxt app with many request to the same API, but also i need to make request to different providers apart of my main API and i don't know how to manage the default headers.
This is my working setup create a plugin to add the headers to all the request like this:
plugins/axios.js
export default function({ $axios, store, redirect }) {
$axios.onRequest(config => {
config.headers.common.Authorization = 'token 123';
config.headers.common["Custom-header"] = 'blablabla';
}
}
nuxt.config.js
module.exports = {
plugins: ["#/plugins/axios"],
axios: {
baseURL: process.env.API_URL,
}
}
store.js
async changeKeyVersionOnline({ commit }) {
const response = await this.$axios.get(
`users/1`
);
return response;
},
This works great for the main API but the problem is i need also to make request to other endpoints of third party service provider and of course the headers should be different.
How can i do that, i read about the proxy option of the nuxt-axios package but what i understand is this only changes the request base URL, i cant find how to set different headers to a specific request.
My final solution was based on create some actions in a central store so the axios requests are made trough this actions.
central.js (Where the axios related actions live)
import qs from "qs";
export const state = () => ({
accessToken: "",
clientId: 0
});
export const getters = {
getHeadersWithAuth: state => {
const config = {
headers: {
Authorization: "Bearer " + state.accessToken
}
};
return config;
},
getHeadersWithAuthClient: state => {
const config = {
headers: {
Authorization: "Bearer " + state.accessToken,
Client: state.clientId
}
};
return config;
}
};
export const mutations = {};
export const actions = {
async getWithAuth({ getters }, { path, params }) {
const config = getters.getHeadersWithAuth;
config.params = params;
config.paramsSerializer = function(params) {
return qs.stringify(params, { encode: false });
};
const result = await this.$axios.get(path, config);
return result;
},
async getWithAuthClient({ getters }, { path, params }) {
const config = getters.getHeadersWithAuthClient;
config.params = params;
config.paramsSerializer = function(params) {
return qs.stringify(params, { encode: false });
};
const result = await this.$axios.get(path, config);
return result;
},
async putWithAuthClient({ getters }, { path, body, params }) {
const config = getters.getHeadersWithAuthClient;
config.params = params;
config.paramsSerializer = function(params) {
return qs.stringify(params, { encode: false });
};
const result = await this.$axios.put(path, body, config);
return result;
}
};
test.js Other store which use the custom axios requests
async updateProductDetailsAction({ commit, dispatch, state }, productData) {
const request = {
path: `endpoints/` + productData.id + `/details`,
body: {
length: 123,
name: 'The product name'
},
params: {}
};
const result = await dispatch("auth/putWithAuthClient", request, {
root: true
});
await commit("setProductDetails", productData.id);
return result;
}

upload an image to amazon s3 in react-native

I am trying to upload image to amazon s3,If possible can any one provide links /docs for how to upload to amazon s3, any help much appreciated
S3 options:
// this.state.s3options in YourComponent
{
"url": "https://yourapp.s3.eu-central-1.amazonaws.com",
"fields": {
"key": "cache/22d65141b48c5c44eaf93a0f6b0abc30.jpeg",
"policy": "eyJleHBpcm...1VDE0Mzc1OVoifV19",
"x-amz-credential": "AK...25/eu-central-1/s3/aws4_request",
"x-amz-algorithm": "AWS4-HMAC-SHA256",
"x-amz-date": "20161125T143759Z",
"x-amz-signature": "87863c360...b9b304bfe650"
}
}
Component:
class YourComponent extends Component {
// ...
// fileSource looks like: {uri: "content://media/external/images/media/13", isStatic: true}
async uploadFileToS3(fileSource) {
try {
var formData = new FormData();
// Prepare the formData by the S3 options
Object.keys(this.state.s3options.fields).forEach((key) => {
formData.append(key, this.state.s3options.fields[key]);
});
formData.append('file', {
uri: fileSource.uri,
type: 'image/jpeg',
});
formData.append('Content-Type', 'image/jpeg')
var request = new XMLHttpRequest();
request.onload = function(e) {
if (e.target.status === 204) {
// Result in e.target.responseHeaders.Location
this.setState({avatarSourceRemote: {uri: e.target.responseHeaders.Location}})
}
}.bind(this)
request.open('POST', this.state.s3options.url, true);
request.setRequestHeader('Content-type', 'multipart/form-data');
request.send(formData);
} catch(error) {
console.error(error);
}
}
// Example display the uploaded image
render() {
if (this.state.avatarSourceRemote) {
return (
<Image source={this.state.avatarSourceRemote} style={{width: 100, height: 100}} />
);
} else {
return (
<Text>No Image</Text>
);
}
}
}
This works for me
import fs from 'react-native-fs';
import {decode} from 'base64-arraybuffer';
import AWS from 'aws-sdk';
export const uploadFileToS3 = async (file) => {
const BUCKET_NAME = 'XXXXXXXXXX';
const IAM_USER_KEY = 'XXXXXXXXXX';
const IAM_USER_SECRET = 'XXXXXXXXXXXXXXX';
const s3bucket = new AWS.S3({
accessKeyId: IAM_USER_KEY,
secretAccessKey: IAM_USER_SECRET,
Bucket: BUCKET_NAME,
signatureVersion: 'v4',
});
const contentType = file.type;
const contentDeposition = `inline;filename="${file.name}"`;
const fPath = file.uri;
const base64 = await fs.readFile(fPath, 'base64');
const arrayBuffer = decode(base64);
return new Promise((resolve, reject) => {
s3bucket.createBucket(() => {
const params = {
Bucket: BUCKET_NAME,
Key: file.name,
Body: arrayBuffer,
ContentDisposition: contentDeposition,
ContentType: contentType,
};
s3bucket.upload(params, (error, data) => {
utils.stopLoader();
if (error) {
reject(getApiError(error));
} else {
console.log(JSON.stringify(data));
resolve(data);
}
});
});
});
};
This worked for me after a significant amount of trying over and over again...
I am also using a lambda function to serve me the link to post with.
The lambda function is just using getSignedUrl.
// Lambda Function
const AWS = require('aws-sdk')
AWS.config.update({
accessKeyId: {bucket_access},
secretAccessKey: {bucket_secret},
signatureVersion: 'v4',
region: {bucket_region}
})
const s3 = new AWS.S3()
exports.handler = async (event) => {
const URL = s3.getSignedUrl('putObject', {Bucket: {bucket_name},
// name of file name being placed in S3 Bucket
// event === metaData object
Key: `${event.{key}}/photo00`})
return URL
};
// React Native
const imagePreview = '{image_uri}'
const handleURL = async () => {
// metaData object
const obj = {
key: "meta_data"
}
const response = await fetch{{lambda_func_endpoint}, {
method: 'POST',
body: JSON.stringify(obj)
})
const json = await response.json();
return json
}
const handleUpload = async () => {
const URL = await handleURL()
const imageExt = imagePreview.split('.').pop()
// I have no idea why you are supposed to fetch before fetching...
// makes no sense. But it works. Lots of trying as I said.
let image = await fetch(imagePreview)
// I have no idea why it needs to be a blob in order
// to upload... makes no sense.
image = await image.blob()
await fetch(URL, {
method: 'PUT',
body: image,
headers: {
Accept: `image/${imageExt}`,
'Content-Type': `image/${imageExt}`
}
})
.then((res) => console.log(JSON.parse(JSON.stringify(res)).status))
.catch((err) => console.error(err))
}
Let me know what you guys think!