Error during upload image to imgur - inavlid URL - image

i have some troubles with imgur api. I converted image to base64 code and tried upload it to imgur api. Unfortuatelly I'm receiving an error:
"error": "Invalid URL (data:image/png;base64,iVBORw0KGgoAA..."
Here's my function:
uploadImageToImgur: function (file) {
const url = 'https://api.imgur.com/3/image',
reader = new FileReader();
reader.onloadend = async function () {
let { result } = reader;
try {
const request = await fetch(url, {
method: 'POST',
headers: {
"Authorization": 'my client key',
},
body: result
});
const response = await request.json();
console.log(response);
} catch (e) {
throw new Error(e);
}
}
if (file) {
reader.readAsDataURL(file);
}
}

You need to cut this part out.

You are missing some parameters. Also, make sure your headers have the Client-ID key.
const request = await fetch(url, {
method: 'POST',
headers: {
"Authorization": 'Client-ID {yourKey}',
},
form: {
"image": result,
"type": "base64"
}
});

Related

Unable to upload pdf file in POST request using Cypress 6.4.0 & TypeScript

I am writing API tests using Cypress 6.4.0 & TypeScript where I need to upload a pdf file in the request body.
My code for the request is:
My code for the request body is:
public async createAssetDocTest() {
let url = sharedData.createAsset_url + sharedData.assetA;
let response = await fetch(url
,
{
method: 'POST',
body: await requestbody.createAssetDocBody(),
headers: {
Authorization: sharedData.bearer + " " + adminTokenValue,
Accept: sharedData.accept,
'Content-type': sharedData.docReqContent,
},
}
);
expect(response.status).to.equal(200);
public async createAssetDocBody(): Promise<any> {
const file = sharedData.doc;
cy.fixture(file).then((pdfDoc) => {
Cypress.Blob.binaryStringToBlob(
pdfDoc,
sharedData.contentTypeValue
).then(async (blob: string | Blob) => {
const formData = new FormData();
formData.set(sharedData.document, blob, file);
const body = {
formdata: {
document: {
value: pdfDoc,
options: {
filename: sharedData.document,
contentType: null,
},
},
},
};
return body;
});
});
}
However, the file does not upload the file & the request fails with error 400. Is there a better way to upload files in the body of the POST request?
enter image description here
Resolved this issue!
The main issue was that my Cypress version was too old. Upgraded to 9.7.0
Then added the following code:
public async createAssetDoc(): Promise<any> {
cy.fixture("pic location", "binary")
.then((file) => Cypress.Blob.binaryStringToBlob(file))
.then((blob) => {
var formdata = new FormData();
formdata.append("document", blob, "pic location");
const url = "your url";
cy.request({
url,
method: "POST",
body: formdata,
headers: {
Authorization:
"bearer" + " " + token,
Accept: "application/json",
"Content-Type": "multipart/form-data",
},
}).then((response) => {
expect(response.status).to.equal(201);
expect(response.statusText).to.equal(
sharedData.fileUploadStatusText
);
const finalResponse = String.fromCharCode.apply(
null,
new Uint8Array(response.body)
);
return finalResponse;
});
});
}

Posting image from expo and axios to spring boot server returns error

I wanna send an axios request with photo data to my Spring Boot server but it does not work.
Here is the code:
const updateUserProfile = dispatch => async ({categories, phoneNumber, photo}) => {
try {
const id = await SecureStore.getItemAsync('user_id');
const formData = new FormData()
formData.append("file", {
uri: photo,
name: `${id}_photo`,
type: 'image/png'
})
await request.post(
`/photos/${id}`,
formData,
{
headers: {
'Content-Type': `multipart/form-data; boundary=${formData._boundary}`
},
},
)
dispatch({type: 'update_user_profile', payload: response.data})
} catch (e) {
dispatch({type: 'add_error', payload: 'UPDATE_USER_PROFILE_ERROR'})
}
}
The file URI looks like that and I think its correct:
file:///data/user/0/[...]/ImagePicker/e9255306-dca9-486e-a9
05-e4e1c619b766.jpg
And here is the Spring Boot Controller
#PostMapping("/{userId}")
public void saveObject(#RequestParam(value = "file") MultipartFile file, #PathVariable Long userId) {
photoService.uploadFile(file, userId);
}
Spring Boot works great when I send request with photo from postman but when I want to send the request from updateUserProfile method above, I receive this error:
Resolved [org.springframework.web.multipart.support.MissingServletRequestPartException: Required request part 'file' is not present]
Okay, finally after many hours I fixed the problem. This github issue helped me a lot https://github.com/axios/axios/issues/4412
So I installed form-data package
npm i form-data
and in the updateUserProfile method added this line just before appending data to formData
FormData.prototype[Symbol.toStringTag] = 'FormData';
so the full method looks like that now:
const updateUserProfile = dispatch => async ({categories, phoneNumber, photo}) => {
try {
const id = await SecureStore.getItemAsync('user_id');
const extenstion = photo.substring(photo.lastIndexOf('.') + 1)
const fileName = photo.replace(/^.*[\\\/]/, '')
const formData = new FormData()
FormData.prototype[Symbol.toStringTag] = 'FormData';
formData.append("file", {
uri: photo,
name: fileName,
type: `image/${extenstion}`
})
await request.post(
`/photos/${id}`,
formData,
{
headers: {
'Content-Type': `multipart/form-data; boundary=${formData._boundary}`
},
},
)
dispatch({type: 'update_user_profile', payload: response.data})
} catch (e) {
dispatch({type: 'add_error', payload: 'UPDATE_USER_PROFILE_ERROR'})
}
}

gapi.client.drive.files.create does not work

I'm writing a vue app. I read this sample code and wrote code like this:
const apiKey = 'mykey';
const discoveryDocs = ["https://www.googleapis.com/discovery/v1/apis/drive/v3/rest"]
const clientId = 'myclientid'
const scopes = 'https://www.googleapis.com/auth/drive.appdata'
function handleClientLoad() {
gapi.load('client:auth2', initClient);
}
function initClient() {
gapi.client.init({
apiKey,
discoveryDocs,
clientId,
scope: scopes
}).then(function () {
createFile()
});
}
function createFile() {
console.log('createFile')
var fileMetadata = {
'name': 'config.json',
'parents': ['appDataFolder']
};
var media = {
mimeType: 'application/json',
body: "body"
};
gapi.client.drive.files.create({
resource: fileMetadata,
media,
fields: 'id'
}, function (err, file) {
console.log('function in createFile')
if (err) {
console.error(err);
} else {
console.log('Folder Id:', file.id);
}
});
}
window.onload=handleClientLoad()
In the console, 'createFile' is logged but 'function in createFile' is not logged, so I think function(err, file)... does not work.
What is wrong?
I want the sample code to work.
I had the same issue. The function create() returns a promise, to execute the request, it seems to need a then(). See also this post.
The example code though does not work since you will get a 403 The user does not have sufficient permissions for this file error. This seems to happen since example code will create the file not in appDataFolder but in the root directory.
I managed to get it to work using the following code. Putting all request parameters flat into the object passed to create() seems to do the trick.
const s = new Readable();
s.push("beep"); // the string you want
s.push(null);
gapi.client.drive.files
.create({
name: "config.json",
parents: ["appDataFolder"],
mimeType: "application/json",
upload_type: "media",
fields: "id",
body: s,
})
.then(function (response) {
if (response.status === 200) {
var file = response.result;
console.log(file);
}
})
.catch(function (error) {
console.error(error);
});

FormData upload on Expo

Using expo, whenever I run a post request with a FormData object with an appended JSON and a image file, I get
"error": "Unsupported Media Type",
"message": "Content type 'application/octet-stream' not supported",
"path": "/visitas/",
"status": 415,
[…]
as a response from the backend (which runs Spring Boot), but whenever I replicate the request into a HTTP Client (Insomnia on this case) the request follow as it should, and I can retrieve and see the image back as I should.
Code
Visitas.js
[…]
async function startVisita(checkin) {
// Checkin contains file uri and some other things
try {
const location = await getLocation();
const formData = new FormData();
formData.append('object',
JSON.stringify({
longitude: location.coords.longitude,
latitude: location.coords.latitude,
checkin: new Date(),
loja: {id: loja.id},
})
);
// object gets filled accondingly
formData.append('imagecheckin', {
uri: checkin.uri,
name: 'imagem.jpg', // I know the image is .jpg
type: 'image/jpg',
});
// imagecheckin is a object inside formData (not a readStream as it normally would)
console.log(formData);
try {
const response = await fetch(`${Endpoint.baseAddr}${Endpoint.visitas}`, {
body: formData,
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'multipart/form-data',
'Authorization': 'Bearer ' + await AsyncStorage.getItem('jwt'),
},
})
.then(res => res.json());
console.log(response);
} catch (err) {
console.error('Erro ao postar a visita! Erro causado:', err);
console.log(err.res, err.response);
}
} catch (err) {
console.error('Erro ao criar a visita! Erro causado:');
console.error(err);
}
}
[…]
ControllerImagens.java
[…]
#PostMapping
public ResponseEntity<T> adicionarCheckin(
#RequestPart(name = "imagecheckin", required = true) MultipartFile file,
#RequestPart(name = "object", required = true) T objeto,
#RequestHeader("authorization") String token) {
// Calls constructors, validators and stuff
[…]
And the formdata I get from the log is
FormData {
"_parts": Array [
Array [
"object",
"{\"longitude\":-40.3097038,\"latitude\":-20.3758293,\"checkin\":\"2020-04-29T18:06:22.994Z\",\"loja\":{\"id\":1}}",
],
Array [
"imagecheckin",
Object {
"name": "imagem.jpg",
"type": "image/jpg",
"uri": "file:///data/user/0/host.exp.exponent/cache/ExperienceData/%2540anonymous%252Fproatend-f576a9db-3f86-4238-8677-3ebbd056f4ea/Camera/1f2192a7-fe81-40d1-8efd-9ff6a98a32a3.jpg",
},
],
],
}

uploading profile pic in hapijs 17.0

I am using hapijs version 17.0.1. I am trying to upload an image using ajax request on a hapijs route. Here is my AJAX code to upload profile pic:
var image_file_input = document.getElementById("user_profile_upload");
image_file_input.onchange = function () {
if(this.files != undefined)
{
if(this.files[0] != undefined)
{
var formData = tests.formdata ? new FormData() : null;
if (tests.formdata)
{
//alert(file)
formData.append('image_file', this.files[0]);
formData.append('userId', user_id);
formData.append('memberId', member_id);
}
$.ajax({
url: "/v1/User/uploadUserPic",
data: formData,
type: "POST",
dataType: "json",
contentType: false,
processData: false,
contentType: "multipart/form-data",
success: function(data){
console.log(data);
var errMsg = null;
var resData = null;
if(data.statusCode == 200)
{
resData = data.result;
}
else
{
alert(data.message)
}
},
error: function(error){
alert(error);
}
});
}
}
}
And here is my Hapijs route Code:
var uploadUserPic = {
method: 'POST',
path: '/v1/Module/uploadUserPic',
config: {
description: 'Update Image For User',
tags: ['api', 'User'],
auth: 'session',
payload: {
output: 'stream',
parse: true,
allow: 'multipart/form-data'
},
validate: {
payload: {
userId : Joi.string().regex(/^[a-f\d]{24}$/i).required(),
memberId: Joi.string().required(),
image_file: Joi.object().required(),
},
failAction: FailCallBack
}
},
handler: function (request, reply) {
var resultData = null;
var error = null;
return new Promise(function (resolve) {
var multiparty = require('multiparty');
var fs = require('fs');
var form = new multiparty.Form();
form.parse(request.payload, function (err, fields, files) {
if(err)
{
error = err;
resolve();
}
else
{
var mkdirp = require('mkdirp');
var img_dir = "./files/users/";
mkdirp(img_dir, function (err) {
if (err)
{
error = err;
console.error(err);
resolve();
}
else
{
var oldpath = files.image_file.path;
var newpath = "./files/users/"+requestPayload.userId+".png";
fs.rename(oldpath, newpath, function (err) {
if(err)
{
error = err;
}
resolve();
});
}
});
}
});
}).then(function (err, result) {
if(err) return sendError(err);
if(error) return sendError(error)
return {
"statusCode": 200,
"success": true
};
});
}
}
The above code gives me following error cannot read property 'content-length' of undefined on line form.parse(request.payload, function (err, fields, files) {});
Please let me know If I am doing something wrong. If I replace the url in ajax request with anohter url that I have written in php then it works perfectly. which means that something is wrong with my hapijs/nodejs code.
There's a good post on how to handle file uploads in Hapi.js (written in version 16) https://scotch.io/bar-talk/handling-file-uploads-with-hapi-js
Since you are using payload.parse = true, I am not seeing a particular reason why you have to use multiparty. I have the following working code that would save files (of any type) uploaded from client into uploads directory on the server (Please do not use directly on production as no sanitation is done)
{
path: '/upload',
method: 'POST',
config: {
payload: {
output: 'stream',
parse: true,
allow: 'multipart/form-data'
},
validate: {
payload: {
files: Joi.array().single()
}
}
},
handler: function(request) {
const p = request.payload, files = p.files
if(files) {
console.log(`${files.length} files`)
files.forEach(async file => {
const filename= file.hapi.filename
console.log(`Saving ${filename} to ./uploads`)
const out = fs.createWriteStream(`./uploads/${filename}`)
await file.pipe(out)
})
}
return {result: 'ok'}
}
}
You can use the following curl command to test
curl http://localhost:8080/upload -F 'files=#/path/to/a/note.txt' -F 'files=#/path/to/test.png' -vvv
There are a few issues with your code. First in your $.ajax call, you have specified contentType twice, although it's not a syntax error but it's careless to code like that. Second the function's signature inside your .then() block is incorrect. You are mixing the idea of Promise and callback. I don't think the following line will be triggered
if(err) return sendError(err);
One last trivial thing, you said you are using Hapi 17 but based on the handler function's signature
handler: function (request, reply) {
...
Seems you are not totally onboard with Hapi17 as the new signature is
handler: function (request, h) {
And it's not just the rename of reply to h.

Resources