I am currently using nativescript-background-http to upload images and I was just wondering is there a way to get the response body or response header coming from the server after sending the image?
Just in case someone has the same problem a year later:
task.on("responded", (e) => {
JSON.parse(e.data)
}
The way I was able to get the response back from the server was in the complete method use the getBodyAsString() method and parse it.
task.on("complete", (ev: any) => {
console.log("Upload complete");
let sr = JSON.parse(ev.response.getBodyAsString());
});
function sendImages(uri, fileUri) {
imageName = extractImageName(fileUri);
var request = {
url: "http://httpbin.org/post",
method: "POST",
headers: {
"Content-Type": "application/octet-stream",
"File-Name": imageName
},
description: "{ 'uploading': " + imageName + " }"
};
var task = session.uploadFile(fileUri, request);
task.on("progress", logEvent);
task.on("error", logEvent);
task.on("complete", logEvent);
function logEvent(e) {
console.log("----------------");
console.log('Status: ' + e.eventName);
// console.log(e.object);
if (e.totalBytes !== undefined) {
console.log('current bytes transfered: ' + e.currentBytes);
console.log('Total bytes to transfer: ' + e.totalBytes);
}
}
return task;
}
Based on this demo
Related
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;
});
});
}
I'm trying to use Microsoft Azure OCR API service to extract some text from an image.
The image I have for sending to the API service has a "data:image/png; base64, " structure and therefore I can't send it with content-type "application/json".
I tried sending it with content-type "multipart/form-data" or "application/octet-stream", but it also fails...
// this "url" gives me the "data:data:image/png;base64, " code
var sourceImageUrl = document.getElementById("myImage").src;
// Perform the REST API call.
$.ajax({
url: uriBase + "?" + $.param(params),
// Request headers.
beforeSend: function(jqXHR){
jqXHR.setRequestHeader("Content-Type","multipart/form-data");
jqXHR.setRequestHeader("Ocp-Apim-Subscription-Key", subscriptionKey);
},
type: "POST",
// Request body.
data: [sourceImageUrl]
})
.done(function(data) {
// Show formatted JSON on webpage.
$("#responseTextArea").val(JSON.stringify(data, null, 2));
})
.fail(function(jqXHR, textStatus, errorThrown) {
// Display error message.
var errorString = (errorThrown === "") ?
"Error. " : errorThrown + " (" + jqXHR.status + "): ";
errorString += (jqXHR.responseText === "") ? "" :
(jQuery.parseJSON(jqXHR.responseText).message) ?
jQuery.parseJSON(jqXHR.responseText).message :
jQuery.parseJSON(jqXHR.responseText).error.message;
alert(errorString);
});
I am bit confused about how I should be sending the image or if I should do some transformations.
Which content-type should I be using to do a proper request?
Should I change the encoding of the image source? How?
Thank you all!
I finally got it working by adding a makeBlob function that returns a blob out of a base64 code. I also set the content-type to "application/octet-stream".
Final code looks like this:
function makeblob(b64Data, contentType, sliceSize) {
contentType = contentType || '';
sliceSize = sliceSize || 512;
var byteCharacters = atob(b64Data);
var byteArrays = [];
for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) {
var slice = byteCharacters.slice(offset, offset + sliceSize);
var byteNumbers = new Array(slice.length);
for (var i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(i);
}
var byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}
var blob = new Blob(byteArrays, { type: contentType });
return blob;
}
function recognizeText() {
imageToSend = image.src;
binDataImage = imageToSend.replace("data:image/png;base64,","");
// Perform the REST API call.
$.ajax({
url: uriBase + "?" + $.param(params),
// Request headers.
beforeSend: function(jqXHR){
jqXHR.setRequestHeader("Content-Type","application/octet-stream");
jqXHR.setRequestHeader("Ocp-Apim-Subscription-Key", subscriptionKey);
},
type: "POST",
// Request body.
data: makeblob(binDataImage, 'image/jpeg'),
cache: false,
processData: false
})
.done(function(data) {
// Show formatted JSON on webpage.
$("#responseTextArea").val(JSON.stringify(data, null, 2));
})
.fail(function(jqXHR, textStatus, errorThrown) {
// Display error message.
var errorString = (errorThrown === "") ?
"Error. " : errorThrown + " (" + jqXHR.status + "): ";
errorString += (jqXHR.responseText === "") ? "" :
(jQuery.parseJSON(jqXHR.responseText).message) ?
jQuery.parseJSON(jqXHR.responseText).message :
jQuery.parseJSON(jqXHR.responseText).error.message;
alert(errorString);
});
};
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"
}
});
I have a HTML form for filling the personal profile, which includes String and Images. And I need to post all these data as JsonObject with one backend api call, and the backend requires the image file sent as binary data. Here is my Json Data as follow:
var profile = {
"userId" : email_Id,
"profile.name" : "TML David",
"profile.profilePicture" : profilePhotoData,
"profile.galleryImageOne" : profileGalleryImage1Data,
"profile.referenceQuote" : "Reference Quote"
};
and, profilePhotoData, profileGalleryImage1Data, profileGalleryImage2Data, profileGalleryImage3Data are all image Binary data(Base64).
And here is my post function:
function APICallCreateProfile(profile){
var requestUrl = BASE_URL + API_URL_CREAT_PROFILE;
$.ajax({
url: requestUrl,
type: 'POST',
data: profile,
dataType:DATA_TYPE,
contentType: CONTENT_TYPE_MEDIA,
cache:false,
processData:false,
timeabout:API_CALL_TIMEOUTS,
success: function (response) {
console.log("response " + JSON.stringify(response));
var success = response.success;
var objectData = response.data;
if(success){
alert('CreateProfile Success!\n' + JSON.stringify(objectData));
}else{
alert('CreateProfile Faild!\n'+ data.text);
}
},
error: function(data){
console.log( "error" +JSON.stringify(data));
},
failure:APIDefaultErrorHandler
})
.done(function() { console.log( "second success" ); })
.always(function() { console.log( "complete" ); });
return false;
}
But still got failed, I checked the server side, and it complains about the "no multipart boundary was found".
Can anyone help me with this, thanks:)
Updates:
var DATA_TYPE = "json";
var CONTENT_TYPE_MEDIA = "multipart/form-data";
I think I found the solution with vineet help. I am using XMLHttpRequest, and didn't set the requestHeader, but it works, very strange. But hope this following can help
function APICallCreateProfile(formData){
var requestUrl = BASE_URL + API_URL_CREAT_PROFILE;
var xhr = new XMLHttpRequest();
xhr.onreadystatechange=function()
{
if (xhr.readyState==4 && xhr.status==200){
console.log( "profile:" + xhr.responseText);
}else if (xhr.readyState==500){
console.log( "error:" + xhr.responseText);
}
}
xhr.open('POST', requestUrl, true);
// xhr.setRequestHeader("Content-Type","multipart/form-data; boundary=----WebKitFormBoundarynA5hzSDsRj7UJtNa");
xhr.send(formData);
return false;
}
Why to reinvent the wheel. Just use Jquery Form Plugin, here. It has example for multipart upload as well.
You just need to set input type as file. You will receive files as input stream at server (off course they will be multipart)
I was wondering how to convert Variable-length binary data(255216255224016747073700110010100255) to a jpeg or png to the web browser?
Example Code:
var Connection = require('tedious').Connection;
var config = {
"userName": "user#server.database.windows.net",
"password": "pswd",
"server": "server.database.windows.net",
"options": {
"database": "db",
"encrypt": true,
}
};
var connection = new Connection(config);
connection.on('connect', function(err) {
console.log("Connected");
}
);
var Request = require('tedious').Request;
var result,
resG;
function sendResponse() {
var vals;
// Convert to string then array
var resultA = result.toString().split(',');
// Now I can loop through the data returned
resultA.forEach(function(val, index, ar) {
if(vals == null) {
vals = val;
} else {
vals += val;
}
});
resG.writeHead(200, {'Content-Type': 'text/html', 'Content-Length': vals.length});
//console.log(vals);
//resG.end("<img src=\"data:image/jpg;base64," + vals + "\" />");
// Output data returned from db as string
resG.end("" + vals);
}
function executeStatement() {
request = new Request("SELECT Photos FROM dbo.tbl WHERE FarmerFirstName='someName' AND FarmerLastName='someLastName'", function(err, rowCount) {
if (err) {
console.log(err);
} else {
console.log(rowCount + ' rows');
}
});
request.on('row', function(columns) {
columns.forEach(function(column) {
result = column.value;
});
});
request.on('doneInProc', function(rowCount, more) {
// Got everything needed from db move on to sending a response
sendResponse();
});
connection.execSql(request);
}
var http = require('http'),
director = require('director');
var router = new director.http.Router({
"/": {
get: executeStatement
}
});
var server = http.createServer(function (req, res) {
// set global res var
resG = res;
router.dispatch(req, res, function (err) {
if (err) {
res.writeHead(404);
res.end();
}
});
});
server.listen(80);
I'm using tedious for my db connector and director as my router.
The result is already an array of bytes for the Image. You do not need to do any fancy transformations on it. This should work.
function sendResponse() {
resG.writeHead(200, {'Content-Type': 'image/jpeg', 'Content-Length': result.length});
resG.end(new Buffer(result));
}
or if you want to serve it as part of an HTML page, this:
function sendResponse() {
resG.writeHead(200, {'Content-Type': 'text/html'});
var vals = (new Buffer(result)).toString('base64')
resG.end("<html><body>" +
"<img src=\"data:image/jpg;base64," + vals + "\" />" +
"</body></html>");
}