I'm trying to upload an image to slack using the slack api https://api.slack.com/methods/files.upload.
function uploadImage(file) {
var form = new FormData();
form.append('image', file);
var self = this;
const config = {
headers: {
'content-type': 'multipart/form-data'
}
}
var token = 'myToken'
axios.post('https://slack.com/api/files.upload?token=' + token, form, config)
.then(function (response) {
console.log(response);
self.imageUploaded("Image uploaded")
})
.catch(function (error) {
console.log(error);
self.error(error);
})
}
I'm getting response with "invalid form data". Any idea what might be going wrong?
Thanks and best regards!
PS: I was able to post an image to slack with python
def post_image(filename, token, channels):
f = {'file': (filename, open(filename, 'rb'))}
response = requests.post(url='https://slack.com/api/files.upload',
data={'token': token, 'channels': channels},
headers={'Accept': 'application/json'},
files=f)
return response.tex
Just need to make the same request with axioms
you can upload a file using axios with the form-data lib
const fs = require("fs");
const axios = require("axios");
const FormData = require("form-data");
const form = new FormData();
form.append("token", 'token here');
form.append("channels", channelId);
form.append("file", fs.createReadStream(__dirname + "/aapl.png"), 'file name');
try {
const res = await axios.post("https://slack.com/api/files.upload", form, {
headers: form.getHeaders(),
});
} catch (err) {
throw new Error(err);
}
Related
I am trying to use the Piniata api. Here it is:
https://docs.pinata.cloud/
The idea is to upload and pin and image using the api, into my account in Piniata.
I got this sample to upload a file in base64, using Node.js and server side.
The sample use this api call:
"https://api.pinata.cloud/pinning/pinFileToIPFS"
I am suppose to be able to do this in client side as well.
However, there is no sample of client side without using Node.js. And I can't seem to find exactly a documentation of what the api call expects.
Here is the sample I got from the Piniata support:
const { Readable } = require("stream");
const FormData = require("form-data");
const axios = require("axios");
(async () => {
try {
const base64 = "BASE64 FILE STRING";
const imgBuffer = Buffer.from(base64, "base64");
const stream = Readable.from(imgBuffer);
const data = new FormData();
data.append('file', stream, {
filepath: 'FILENAME.png'
})
const res = await axios.post("https://api.pinata.cloud/pinning/pinFileToIPFS", data, {
maxBodyLength: "Infinity",
headers: {
'Content-Type': `multipart/form-data; boundary=${data._boundary}`,
pinata_api_key: pinataApiKey,
pinata_secret_api_key: pinataSecretApiKey
}
});
console.log(res.data);
} catch (error) {
console.log(error);
}
})();
Here is my attempt to perform an upload from client side without Node.js
async function uploadFile(base64Data)
{
const url = `https://api.pinata.cloud/pinning/pinFileToIPFS`;
var status = 0;
try {
let data = new FormData();
var fileName = "FILENAME.png";
var file = new File([base64Data], fileName, {type: "image/png+base64"});
data.append(`data`, file, file.name);
data.append(`maxBodyLength`, "Infinity");
const response = await postData('POST', url, {
'Content-Type': `multipart/form-data; boundary=${data._boundary}`,
"Authorization": "Bearer Redacted"
},
data
);
} catch (error) {
console.log('error');
console.log(error);
}
}
What I get as a response from the server is 400 and the error being:
{"error":"Invalid request format."}
What am I doing wrong?
Also, it seems like when I try to use FormData .append with a stream as a sample, it doesn't work. As if it only expects a blob.
when I'm trying to call the request in front node, I'm getting error in my backend node " RequestError: Error: Invalid URI "undefined"" , it seems like backend node request is not getting the data form my frontend node request.
knowing that uploadLink already have a value and in my browser console the frontend request looks ok
my backend request code
const ThumbnailUpload = async (req, res) => {
const { Uploadlink } = req.body;
const { selectedFile } = req.body;
const clientServerOptions = {
uri: `${Uploadlink}`,
body: JSON.stringify({
name: selectedFile,
}),
method: 'PUT',
headers: {
'Content-Type': ' application/json',
Accept: 'application/vnd.vimeo.*+json;version=3.4',
Authorization: getVimeoAuthorization(),
},
};
request(clientServerOptions, function (error, response) {
if (error) {
res.send(error);
} else {
const body = JSON.parse(response.body);
res.send(body);
}
console.log(Uploadlink);
});
};
and my frontend code is
const handleSubmit = (event) => {
event.preventDefault();
const formData = new FormData();
formData.append(
'selectedFile',
new Blob([selectedFile], { type: 'image/jpg, image/png, or image/gif' }),
);
formData.append('uploadLink', uploadLink);
const headers = {
'Content-Type': 'image/jpg, image/png, or image/gif',
Accept: 'application/vnd.vimeo.*+json;version=3.4',
};
try {
axios
.post(`${backendPostPath}/thumbnail-upload`, formData, {
headers,
})
.then((response) => {
applyThumbnial();
console.log(response);
});
} catch (error) {
console.log(error);
}
};
any advise ?
change:
const { Uploadlink } = req.body;
to:
const { uploadlink } = req.body;
make variable consistent throughout the code
EDIT
also, since you're uploading a file, you need to use upload middleware before request handler, and file will be within req.file:
route.post('/thumbnail-upload', upload.single('selectedFile'), ThumbnailUpload);
//... handler..
const selectedFile = req.file;
I am attempting to upload a file using the Node example provided in the HubSpot docs.
I am receiving 415(Unsupported media type). The response says I am sending the header application/json even though I am setting multipart/form-data.
const uploadFile = async () => {
const postUrl = `https://api.hubapi.com/filemanager/api/v3/files/upload?hapikey=${HAPI_KEY}`;
const filename = `${APP_ROOT}/src/Files/Deal/4iG_-_CSM_Additional_Capacity/test.txt`;
const headers = {
'Content-Type': 'multipart/form-data'
}
var fileOptions = {
access: 'PUBLIC_INDEXABLE',
overwrite: false,
duplicateValidationStrategy: 'NONE',
duplicateValidationScope: 'ENTIRE_PORTAL'
};
var formData = {
file: fs.createReadStream(filename),
options: JSON.stringify(fileOptions),
folderPath: '/Root'
};
try {
const resp = await axios.post(postUrl, formData, headers); // API request
console.log(resp.data)
} catch (error) {
console.log("Error: ", error);
}
}
Can you see what the problem is or recommend a better way of uploading the file?
Thanks!
The Node example you link to uses the (deprecated) request module, not Axios.
To use Axios (source) you would rewrite that as:
const FormData = require('form-data');
const form = new FormData();
form.append('file', fs.createReadStream(filename));
form.append('options', JSON.stringify(fileOptions));
form.append('folderPath', '/Root');
const config = { headers: form.getHeaders() };
axios.post(postUrl, form, config);
We can Run API in Postman and check NodeJs - Axios Detail in Postman Code Snippet and I Think That's the Better way for this.
const axios = require('axios');
const FormData = require('form-data');
const fs = require('fs');
const uploadFile = async () => {
try {
let data = new FormData();
data.append('folderPath', '/Root');
form.append('file', fs.createReadStream(`${APP_ROOT}/src/Files/Deal/4iG_-_CSM_Additional_Capacity/test.txt`));
data.append('options', JSON.stringify({
access: 'PUBLIC_INDEXABLE',
overwrite: false,
duplicateValidationStrategy: 'NONE',
duplicateValidationScope: 'ENTIRE_PORTAL'
}));
var config = {
method: 'post',
url: `https://api.hubapi.com/filemanager/api/v3/files/upload?hapikey=${HAPI_KEY}`,
headers: {
'Content-Type': 'multipart/form-data'
},
data: data
};
const resp = await axios(config); // API request
console.log(resp.data)
} catch (error) {
// error
}
}
presently I am attempting to make 2 different api calls one after the other within 1 java/nodejs script. It seems after my first function runs successfully, the second one errors with the following:
FetchError: request to failed, reason: socket hang up;
type: 'system',
errno: 'ECONNRESET',
code: 'ECONNRESET'
Below is a code snippet of what I have tried thus far:
const fetch = require("node-fetch");
const formData = require("form-data");
const fs = require("fs");
//const express = require("express");
var apiName = "<LOCAL SYSTEM FILE TO UPLOAD>";
var lookupName = "<LOCAL SYSTEM FILE TO UPLOAD>";
var accessToken = "Bearer <ACCESS TOKEN>";
var url = '<URL API #1>';
var url2 = '<URL API #2>;
var headers = {
'Accept': 'application/json',
'Authorization': accessToken,
};
const form = new formData();
const buffer2 = fs.readFileSync(lookupName);
const buffer = fs.readFileSync(apiName);
const uploadAPI = function uploadAPI() {
form.append("Content-Type", "application/octect-stream");
form.append('file', buffer);
fetch(url, {method: 'POST', headers: headers, body: form})
.then(data => {
console.log(data)
})
.catch(err => {
console.log(err)
});
};
const uploadLookup = function uploadLookup() {
form.append("Content-Type", "application/octect-stream");
form.append('file', buffer2);
fetch(url2, {method: 'PUT', headers: headers, body: form})
.then(data => {
console.log(data)
})
.catch(err => {
console.log(err)
});
};
if (!apiName !== true) {
uploadAPI()
} else {}
if (!lookupName !== true) {
console.log("Uploading Lookup File");
uploadLookup()
} else {}
I tried using a "setTimeout" function which does not seem to work as I would have liked it to. My best guess is each API call would need to be it's own separate socket connection? Any help with getting me in the right direction is appreciated.
Promise.all([
fetch(url),
fetch(url2)
]).then(function (res) {
// Get a JSON object from each of the responses
return res.json();
}).then(function (data) {
// do something with both sets of data here
console.log(data);
}).catch(function (error) {
// if there's an error, log it
});
I sign the URL on my server and send it back to the client which works fine. This is how that function looks
const aws = require('aws-sdk'),
config = require('config'),
crypto = require('crypto');
module.exports = async function(file_type) {
aws.config.update({accessKeyId: config.AWS_ACCESS_KEY, secretAccessKey: config.AWS_SECRET_KEY})
const s3 = new aws.S3();
try {
if (!file_type === "image/png") {
return ({success: false, error: 'Please provide a valid video format'});
}
let buffer = await crypto.randomBytes(12);
let key = buffer.toString('hex');
let options = {
Bucket: config.AWS_S3_BUCKET,
Key: key,
Expires: 60,
ContentType: file_type,
ACL: 'public-read',
}
let data = await s3.getSignedUrl('putObject', options);
console.log('data was', data)
return ({
success: true,
signed_request: data,
url: ('https://s3.amazonaws.com/' + config.AWS_S3_BUCKET + '/' + key),
key,
});
} catch (error) {
console.log('the error was', error)
return ({
success: false,
error: error.message,
})
}
}
So this works fine and winds up getting me a url like
https://mybucket.s3.amazonaws.com/a33b4a43f23fc41de9ddck1k?AWSAccessKeyId=ADIFJDGPMRFRGLXSYWPQ&Content-Type=image%2Fpng&Expires=1496716543&Signature=0zcx%2BFzWUoeFD02RF2CQ2o0bLmo%3D&x-amz-acl=public-read
Then when I get that url back on the client.. i send a PUT request using axios with a function like -
function uploadToS3(file, signedRequest, callback){
var options = {
headers: {
'Content-Type': file.type
}
};
axios.put(signedRequest, file, options)
.then(result =>{
console.log('the result was', result)
callback(result)
})
.catch(err =>{
callback(err)
})
}
The only I'm getting back is (400) Bad Request
I faced the same issue and after searching for hours, I was able to solve it by adding the region of my bucket to the server side backend where I was requesting a signed URL using s3.getSignedUrl().
const s3 = new AWS.S3({
accessKeyId:"your accessKeyId",
secretAccessKey:"your secret access key",
region:"ap-south-1" // could be different in your case
})
const key = `${req.user.id}/${uuid()}.jpeg`
s3.getSignedUrl('putObject',{
Bucket:'your bucket name',
ContentType:'image/jpeg',
Key:key
}, (e,url)=>{
res.send({key,url})
})
After getting the signed URL, I used axios.put() at the client side to upload the image to my s3 bucket using the URL.
const uploadConf = await axios.get('/api/uploadFile');
await axios.put(uploadConf.data.url,file, {
headers:{
'Content-Type': file.type
}
});
Hope this solves your issue.
Guess bad header you provided
Works for me
function upload(file, signedRequest, done) {
const xhr = new XMLHttpRequest();
xhr.open('PUT', signedRequest);
xhr.setRequestHeader('x-amz-acl', 'public-read');
xhr.onload = () => {
if (xhr.status === 200) {
done();
}
};
xhr.send(file);
}