My response contains an png, how can I display the image in react since its not a url? - reactjs

I have a response containing an image in png format,but I am unable to display it in react since it is not a url
pic of response
does anyone know how I can convert this png into a URL so I can insert it into my src of img tag?

This is something I did when I was doing a similar thing in a React project.
1) Assuming the following:
The response that we get from the API is not BASE64 encoded
The responseType is not specified in the request
A png is the response
The response data will look like this :
With characters that does not look friendly.
2) With changed responseType
Set responseType: "arraybuffer" in the request
The response will now have arrayBuffer in data of the response
The response can then be converted to base64 by
let base64ImageString = Buffer.from(response.data, 'binary').toString('base64')
If you want to display it on an img tag, then
prepend data:image/png;base64, to the Base64 string
let srcValue = "data:image/png;base64,"+base64ImageString
But in your case, it seems like you are only getting the file name as a string and not the file itself.

Why not treat imege you need as Bese64 string? If you're able to convert you png image to a Base64 string (server side obviously) you can easily use it in img tag as src attribute value.

If you have the image inside your application ( assets folder or whatever ) you could display it like that
<img src={`assets/${coverImage}`}>
Else The image should be sent from the API in the base64 format and then you could simply display it like that.
data = "base64 image"
<img src={`data:image/jpeg;base64,${data}`} />

same in my case. "react": "17.0.1", "react-native": "0.64.2",
my response contains png image(no URL, no base64),
I converted my response into base64 as below,
const makeApiRequest = async()=>{
try {
const response = await apiCaller('ProfileImage',{"thisID": "ABCD","thatID": "1234"})
if(response.status === 200){
const dataResponse = await response.blob()
let blob = new Blob([dataResponse], { type: "text/plain" });
var reader = new FileReader();
reader.readAsDataURL(blob);
reader.onloadend = function () {
var base64String = reader.result;
setImageFromAPI(base64String.substr(base64String.indexOf(', ') + 1)); //Setting response to hook
}
}else{
console.log(response.status)
}
} catch (error) {
console.log("components/profile/ProfileTimeline.js:-",error)
}
}
But when I use it in my image tag its shows no image, and i don't know why
<Image source={{uri: `data:image/png;base64,${imagefromAPI}`}} style={{width:100, height:100}} resizeMode="cover" />

Related

Firebase Storage not displaying image properly (shows a small box)

EDIT: I've updated the CORS config but its still showing the same error.
I have a Tinymce RTE on my page, and when u drop an image into the editor, I have some functions that upload it to firebase storage, then swaps out the src of the text editor with the url fetched from firebase. It works kinda ok, but its being displayed as a broken link image icon.
When I check the link, its because originally it downloads the image when the link is clicked. I added a metadata property when it uploads it, but now its just showing a tiny box.
Here is the code where the image dropped into the editor is uploaded into firebase storage
const imagesUploadHandler = async (blobInfo, success, failure) => {
try {
const file = blobInfo.blob();
const storageRef = ref(storage, file.name);
const metadata = {
contentType: 'image/jpeg',
};
await uploadBytes(storageRef, file, metadata);
const url = await getDownloadURL(storageRef);
console.log(url);
return url;
} catch (error) {
// Call the failure callback with the error message
console.log(error.message);
}
};
Originally, i didnt include the contentType metadata, and it was just uploading as application/octet-stream, which i assume is why it prompts you to save the image.
Image link: https://firebasestorage.googleapis.com/v0/b/cloudnoise-news.appspot.com/o/ref.jpg?alt=media&token=1edc90e7-1668-4a06-92a3-965ce275798b
Currently its displaying this
Somethings i checked through
firebase storage rules is in test mode, so should be able to read and write by anyone.
i tried sticking in different MIME types but it either shows the tiny box, or it shows "undefined"
the files upload successfully and the "swap" in Tinymce editor is also all good.
Any idea why this is happening?
you need to set the metadata tag
const metadata = {
contentType: file.type,
};
This should ensure that the correct content type is set when the image is uploaded to Firebase Storage.
If this does not resolve the issue, you may need to check that the URL returned from getDownloadURL is valid and points to the correct image. You can try opening the URL in a new browser tab to verify that the image is accessible.
I fixed it by adding a blob, I created a blob object with the file data, then i just made it upload the blob object instead of the single file.
const imagesUploadHandler = async (blobInfo, success, failure) => {
try {
const file = blobInfo.blob();
const storageRef = ref(storage, file.name);
const metadata = {
contentType: file.type,
};
// Create a new Blob object with the file data
const blob2 = await new Blob([file], { type: file.type });
// Upload the Blob to Firebase Storage
await uploadBytes(storageRef, blob2, metadata);
const url = await getDownloadURL(storageRef);
console.log(url);
return url;
} catch (error) {
// Call the failure callback with the error message;;
console.log(error.message)
}
};

How to convert Base64 image to BLOB in React js

I have an image in base64. I want to store that in MySQL Database as BLOB. So i want to convert that base64 image into BLOB in react js.
How to perform the convertion. atob is not working in react js for me.
Please help me in resolving this issue.
Thanks in advance.
Width 'canvas-to-blob' library you can convert base64 to blob.
import html2canvas from "html2canvas";
var toBlob = require("canvas-to-blob");
useEffect(() => {
html2canvas(document.getElementById("domEl")).then((canvas) => {
const blobImage = toBlob(canvas.toDataURL("image/png"));
return blobImage
});
}, []);
Here what I am doing is converting my dom element to Base64 with html2canvas library, then I am converting my canvas (base64) to blob using toBlob library.
If you want to send it to the server, you can use the formData constructor:
formData = formData()
formData.append('image', blobImage , 'myimage.png')
Now you can pass formData in your endpoint.!

how to show image from bytes?

I have an API which returns an Image as byte data, but I don't know how can I show this bytes in the src of the img tag
here is an example of what I got in the result
and this is how I use axios to make use of the API
const getFile = async (nombreArchivo) => {
const tokenApp = window.localStorage.getItem('token')
const {data: res} = await axios.get(`${url}photo-2.jpg`,
{ headers: { Authorization: `${tokenApp}` },responseType: 'json',});
return res;};
Add {responseType: 'blob'} to your axios config.
Then use <img src={URL.createObjectURL(responseData)} />to display it.
You can convert the bytes array into the base64 encoding and use this for rendering the image.
byte[] to base64:
const base64String = btoa(String.fromCharCode(...new Uint8Array(arrayBuffer)));
source of the conversion here
Once you have the base64 you can use it into the src field of a standard img tag

upload image to S3 presigned url using react-native-image-picker and axios

I am trying to get an presigned url image upload working correctly. Currently the upload succeeds when selecting an image from the IOS simulator, however when I actually try to view the file it seems the file is corrupted and will not open as an image. I suspect it has something to do with my FormData but not sure.
export async function receiptUpload(file) {
const date = new Date();
const headers = await getAWSHeaders();
const presignUrl = await request.post(
urls.fileUpload.presignUpload,
{file_name: `${date.getTime()}.jpg`},
{headers}
)
.then(res => res.data);
const formData = new FormData();
formData.append('file', {
name: `${date.getTime()}.jpg`,
uri: file.uri,
type: file.type
});
const fileUpload = presignUrl.presignUrl && await request.put(
presignUrl.presignUrl,
formData
)
.then(res => res.status === 200);
}
I have tried from other fixes to change the file uri like so...
Platform.OS === 'android' ? file.uri : file.uri.replace('file://', '');
however this does not seem to work either.
I did this just recently in my current project and the following code is a working example for my use case. I didn't need to convert to a blob either though I am uploading to AWS S3 so if you are uploading elsewhere that may be the issue.
export const uploadMedia = async (fileData, s3Data, setUploadProgress = () => {}) => {
let sendData = { ...fileData };
sendData.data.type = sendData.type;
let formData = new FormData();
formData.append('key', s3Data.s3Key);
formData.append('Content-Type', fileData.type);
formData.append('AWSAccessKeyId', s3Data.awsAccessKey);
formData.append('acl', 'public-read');
formData.append('policy', s3Data.s3Policy);
formData.append('signature', s3Data.s3Signature);
formData.append('file', sendData.data);
return axios({
method: 'POST',
url: `https://${s3Data.s3Bucket}.s3.amazonaws.com/`,
data: formData,
onUploadProgress: progressEvent => {
let percentCompleted = Math.floor((progressEvent.loaded * 100) / progressEvent.total)
setUploadProgress(percentCompleted);
}
})
}
I would first check to see where the issue is occurring. After uploading can you view it on whatever storage service you are trying to upload it to. If so it's something on React Native side. If it doesn't ever get uploaded to the location you know its an error in your upload process. Might help you track the exact location of the error.
I had to do this recently for a project. I believe the data is a base64 string when coming directly from the file input. So the issue is your are uploading a base64 string not the image by simply passing the data field. I had to process it before uploading to the signed URL with the following method.
private dataUriToBlob(dataUri) {
const binary = atob(dataUri.split(',')[1]);
const array = [];
for (let i = 0; i < binary.length; i++) {
array.push(binary.charCodeAt(i));
}
return new Blob([new Uint8Array(array)], { type: 'image/jpeg' });
}
This answer fixed it for me: How can I upload image directly on Amazon S3 in React Native?
I had tried uploading with axios and fetch with FormData. The download went through but the image file was not readable, even when downloaded to my Mac from the S3 console:
The file "yourfile.jpg" could not be opened. It may be damaged or use a file format that Preview doesn’t recognize.
Only after trying to upload with XHR with the correct Content-Type header did it work. Your signedUrl should be correct as well, which seems to be the case if the download goes through.

Why I cannot show my image(.svg) that uploaded to S3

I've uploaded few svg image to a S3 bucket(I'v set to public-all).After I uploaded all svg images.I get each image's URL.When I clicked on those Url it just download the images for me.
Also. Does anyone know why when I use those Url in a img tag (e.g.<img src='https://***.s3.***.amazonaws.com/***.svg />`).It just shows a broken image
Here is my lambda function
'use strict'
const aws = require('aws-sdk')
const s3 = new aws.S3()
const { parse } = require('aws-multipart-parser')
const response = (statusCode, data) => ({
statusCode,
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
},
body: JSON.stringify(data)
})
exports.handler = async event => {
const inputData = parse(event, true)
if (inputData.file) {
try {
const params = {
Bucket: ***,
region: ***,
Key: `${inputData.file.filename}`,
Body: inputData.file.content,
ACL: 'public-read'
}
const s3Response = await s3.upload(params).promise()
return response(200, { statusCode: 200, url: s3Response['Location'] })
} catch (error) {
console.log('Error: ', error)
return response(500, {
error: error.message
})
}
} else {
return response(400, {
error: 'Please provide input file.'
})
}
}
You need to set the content type for you svg image on S3 to "image/svg+xml".
To change the content-type through S3 console :
Select the object on the S3 console
Click on actions
Click on change metadata
Change the content-type to image/svg+xml. The value is already available in the drop down.
As you are using the API gateway to upload the images, you can set the respective content type in you putObject request.
Reference : AWS S3 Put Object API documentation
You can refer the following AWS documentation to upload image with ContentType through JS :
https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#putObject-property
I faced a similar issue with SVGs being served from S3. On opening the svg url on the browser, it was working fine, but on passing the url in the imgs src attribute gave a broken image.
After comparing my svg with other working svgs I found that below attributes were missing in my svg.
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
On adding them it started working fine.
Something like this it has to be -
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
...
...
</svg>
My Front-End developers were complaining about this same issue. Blame AWS!
For some reason, they mark SVG images as binary/octet-stream instead of marking them as image/svg+xml.
My Back-End is developed in Golang and I use the official AWS SDK to Upload the files (https://github.com/aws/aws-sdk-go). What I did to fix the problem was pass by parameter the MimeType (ContentType) of the file.
If you don't pass AWS any MimeTypes then they will try to automatically identify a MimeType for your file, however they can make a mistake in some cases. If you pass a MimeType to AWS they will use your MimeType instead of trying to identify it, and that will likely solve the problem.
In my case in Golang I used this package to be able to automatically identify the MimeType https://github.com/gabriel-vasile/mimetype
var mimeTypePtr *string
mime := mimetype.Detect(file)
if mime != nil {
mimeType := mime.String()
mimeTypePtr = &mimeType
}
uploader := s3manager.NewUploader(cfg)
result, err := uploader.Upload(&s3manager.UploadInput{
Bucket: os.Getenv("AWS_BUCKET"),
Key: filename,
Body: file,
ContentType: mimeTypePtr,
})
In my case SVG image still gets forces download if its mime-type is image/svg
You can fix it by set the mime-type for the file is image/svg+xml

Resources