Download the image returned by an API - javascript

I am working with the sportradar api. The api call that I am making, returns a png image. Till now I have done this.
const apiCall = (url) => {
return axios.get(url).then((data) => {
if(data){
return Promise.resolve(data);
}
else{
return Promise.reject();
}
});
}
//all data in data.assetlist
for(let i=0; i<data.assetlist.length; i++){
let imageLink = data.assetlist[i].links[12].href;
let url = `https://api.sportradar.us/nfl-images-p3/ap_premium${imageLink}?api_key=${api_key}`;
apiCall(url).then((data) => {
console.log(data);
let blob = new Blob(data, {type: "image/png"}); // didn't compile with this line
});
}
The above code is working fine and is returning the data. But the data are weird character, which if I am understanding it correctly, is because of the fact that image is a blob type and I am getting a stream of data.
I took reference from here and wrote this line
let blob = new Blob(data, {type: "image/png"});
I didn't try this, because I am afraid that the data is so big that it might crash my system (old laptop). If I am doing this right, I wanna know, how to save this blob file into my system as a png file and if not then I wanna know how can i convert this stream of data into an image and can download and save it in a local directory.

If the image you get is already a blob you can download it using this library :
https://github.com/eligrey/FileSaver.js
let FileSaver = require('file-saver');
FileSaver.saveAs(blob, "my_image.png");
I think you shouldn't be so worried about the size and just go for it.

After a lot of research, I found this solution and it worked.
apiCall(url).then((response) => {
response.data.pipe(fs.createWriteStream('test.jpg'));
});

Related

React-easy-crop just returns a blob url

I am using react-easy-crop to allow users to modify their profile pictures after uploading. The problem I am experiencing is that after cropping, the image is returned in the form of a blob url like this: blob:http://localhost:3000/5e44190e-a087-4683-b3a4-dfce4a57ee62 which is unhelpful since it can only be viewed on my local machine.
I have tried converting it to a data url (which I understand can then be shared and viewed across browsers), using FileReader and the readAsDataURL() method like this:
let blob = await fetch(imageToCrop).then((r) => r.blob());
let reader = new FileReader();
reader.readAsDataURL(blob);
reader.onloadend = function () {
let base64data = reader.result;
console.log(base64data);
};
The base64data variable does return what I think I need, however all my attempts to then store this result in my state only return a null value.
Does anyone know what is the best way to handle this?
If you have this line in your code, delete it because it revoke your URL.
window.URL.revokeObjectURL(this.fileUrl);
If you need the base64 output of the cropped image, you can get it after using the canvas to crop it with canvas.toDataURL('image/jpeg'). This base64 string can then be shared to anyone or uploaded to a remote server.
This is basically the commented line in the getCroppedImg() function of this demo: https://codesandbox.io/s/q8q1mnr01w?file=/src/cropImage.js:2362-2562
BTW I guess you could also upload the blob to a remote server and store the image somewhere like AWS S3.

MS Graph API file replace SharePoint ReactJS 404 item not found or stream issue

I am trying to use the MS Graph API and ReactJS to download a file from SharePoint and then replace the file. I have managed the download part after using the #microsoft.graph.downloadUrl value. Here is the code that gets me the XML document from SharePoint.
export async function getDriveFileList(accessToken,siteId,driveId,fileName) {
const client = getAuthenticatedClient(accessToken);
//https://graph.microsoft.com/v1.0/sites/{site-id}/drives/{drive-id}/root:/{item-path}
const files = await client
.api('/sites/' + siteId + '/drives/' + driveId + '/root:/' + fileName)
.select('id,name,webUrl,content.downloadUrl')
.orderby('name')
.get();
//console.log(files['#microsoft.graph.downloadUrl']);
return files;
}
When attempting to upload the same file back up I get a 404 itemNotFounderror return. Because this user was able to get it to work I think I have the MS Graph API correct, although I am not sure I'm translating correctly to ReactJS syntax. Even though the error message says item not found I think MS Graph might actually be upset with how I'm sending the XML file back. The Microsoft documentation for updating an existing file state the contents of the file in a stream should be returned. Since I've loaded the XML file into the state I'm not entirely sure how to send it back. The closest match I found involved converting a PDF to a blob so I tried that.
export async function putDriveFile(accessToken,siteId,itemId,xmldoc) {
const client = getAuthenticatedClient(accessToken);
// /sites/{site-id}/drive/items/{item-id}/content
let url = '/sites/' + siteId + '/drive/items/' + itemId + '/content';
var convertedFile = null;
try{
convertedFile = new Blob(
[xmldoc],
{type: 'text/xml'});
}
catch(err) {
console.log(err);
}
const file = await client
.api(url)
.put(convertedFile);
console.log(file);
return file;
}
I'm pretty sure it's the way I'm sending the file back but the Graph API has some bugs so I can't entirely be sure. I was convinced I was getting the correct ID of the drive item but I've seen where the site ID syntax can be different with the Graph API so maybe it is the item ID.
The correct syntax for putting an (existing) file into a document library in SharePoint is actually PUT /sites/{site-id}/drive/items/{parent-id}:/{filename}:/content I also found this code below worked for taking the XML document and converting into a blob that could be uploaded
var xmlText = new XMLSerializer().serializeToString(this.state.xmlDoc);
var blob = new Blob([xmlText], { type: "text/xml"});
var file = new File([blob], this.props.location.state.fileName, {type: "text/xml",});
var graphReturn = await putDriveFile(accessToken, this.props.location.state.driveId, this.state.fileId,file);

How to load an HTML5 Canvas with an image from an image-service?

My web app calls a Web API service, which returns an image. The service returns nothing but an image. Calling the service is little different because there is a function in the routing code that adds the required auth-code and such. Anyway, my point is, I don't have the full URL and even if I did, I wouldn't want to pass it into code in plain-text. So what I have is a response, and that response is an image.
getThumb(filename: string) {
return this.http.get('/Picture/' + filename).subscribe(response => {
return response;
});
}
What I need to do is draw that image on to a canvas. From what I've seen on the internet so far, it looks like I want to create an image element, then assign that element src a URL, then I can add it to the canvas. It's the src part that's perplexing me. All the samples I see are either loading the image from a local filesystem or predefined URL, or from a base64 string, etc. I can't figure out how to just load an image I have as a response from a service. I'm sure I'm overthinking it.
Does anyone have some sample code to illustrate this?
e.g Something like this:
var img = new Image(); // Create new img element
img.src = ... ; // Set source to image
You could convert the image to Base64. In my example, you request the image and convert it to a blob using response.blob(). Once it's a blob, use fileReader.readAsDataURL to get the Base64.
const fileReader = new FileReader();
fetch("image-resource").then((response) => {
if(response.ok) {
return response.blob();
}
}).then((blob) => {
fileReader.readAsDataURL(blob);
fileReader.onloadend = () => {
console.log(fileReader.result);
}
});
References:
readAsDataURL
Blob

Convert HEIC to JPG , using php or JS

Anyone tried to convert a heic to jpg?
I looked at the official repository, but I did'nt understand how it works.
All examples in the repository are working. But when I try to process my photo, made on the iphone, the script refuses to process it.
I've had some luck recently with the conversion using libheif. So I made this library which should greatly simplify the whole process
https://github.com/alexcorvi/heic2any
The only caveat is that the resulting PNG/JPG doesn't retain any of the meta-data that were in the original HEIC.
I managed to convert heic to jpg with the help of heic2any js library (https://github.com/alexcorvi/heic2any/blob/master/docs/getting-started.md)
I converted the picture on client side, then gave it to the input in client side.
Server is seeing it as it was originally uploaded as jpg.
function convertHeicToJpg(input)
{
var fileName = $(input).val();
var fileNameExt = fileName.substr(fileName.lastIndexOf('.') + 1);
if(fileNameExt == "heic") {
var blob = $(input)[0].files[0]; //ev.target.files[0];
heic2any({
blob: blob,
toType: "image/jpg",
})
.then(function (resultBlob) {
var url = URL.createObjectURL(resultBlob);
$(input).parent().find(".upload-file").css("background-image", "url("+url+")"); //previewing the uploaded picture
//adding converted picture to the original <input type="file">
let fileInputElement = $(input)[0];
let container = new DataTransfer();
let file = new File([resultBlob], "heic"+".jpg",{type:"image/jpeg", lastModified:new Date().getTime()});
container.items.add(file);
fileInputElement.files = container.files;
console.log("added");
})
.catch(function (x) {
console.log(x.code);
console.log(x.message);
});
}
}
$("#input").change(function() {
convertHeicToJpg(this);
});
What I am doing is converting the heic picture to jpg, then previewing it.
After that I add it to the original input. Server side will consider it as an uploaded jpg.
Some delay can appear while converting, therefore I placed a loader gif while uploading.

Javascript Blob anchortag download produces corrupted file

the following code downloads a file that can't be opened(corrupt) and I have absolutely no idea why. I've tried this in so many ways but it never works, it always produces a corrupt file. The original file isn't the problem because it opens fine. I'm trying to open mp4, mp3, and image files.
//$scope.fileContents is a string
$scope.fileContents = $scope.fileContents.join(",");
var blob = new Blob([$scope.fileContents], {type: $scope.file.fileDetails.type});
var dlURL = window.URL.createObjectURL(blob);
document.getElementById("downloadFile").href = dlURL;
document.getElementById("downloadFile").download = $scope.file.fileDetails.name;
document.getElementById("downloadFile").click();
window.URL.revokeObjectURL(dlURL);
You need to download the file contents as binary using an ArrayBuffer e.g.
$http.get(yourFileUrl, { responseType: 'arraybuffer' })
.then(function (response) {
var blob = new Blob([response.data], {type: $scope.file.fileDetails.type});
// etc...
});
Sources:
angular solution
plain javascript solution

Categories