I can't get it to work for me with input file. I understand that this code uses fetch and should transform file to fetch but I have no idea.
heic2any:
fetch("https://alexcorvi.github.io/heic2any/demo/1.heic")
.then((res) => res.blob())
.then((blob) => heic2any({
blob,
toType:"image/jpeg",
quality: 0.7
}))
.then((conversionResult) => {
var reader = new window.FileReader();
reader.readAsDataURL(conversionResult);
reader.onloadend = function () {
base64data = reader.result;
console.log(base64data);
document.getElementById("target2").innerHTML = '<a download="image.webp" href="'+base64data+'">Download</a>';
}
})
.catch((e) => {
console.log(e);
});
input file:
<input id="image-file" type="file" onchange="SavePhoto(this)" >
<script><!-- comment -->
function SavePhoto(f)
{
let photo = f.files[0];
}
</script>
This is assuming you have the heic2any node module installed. If you don't you can install it with
npm install heic2any
Blob is one of the object properties and should be 'blob: photo' instead of just blob. Fetch is not necessary if you already have the file from the file input.
function SavePhoto(f) {
let photo = f.files[0];
heic2any({
blob: photo,
toType: 'image/jpeg',
quality: 0.7
}).then(blob => {
//use the converted blob to do whatever
//maybe let newFile = new File(blob, fileName.jpg, { type: 'image/jpeg' }) or something
}, error => {
//handle errors
});
}
Related
How can I convert SVG files to png,jpg or jpeg Files in React.js Because I am trying to send my files to server and server only accepts jpg/jpeg or png. Any help? I only need files in one of these types. I don't need them in url or blob.
The screenshot of file in console
I searched all over the place. There are some but either the solution is for backend or javascript with dom
const [fileImages, setFileImages] = useState<File[]>([]);
const { state } = useAssetReportContext();
const charts = state.chartsList.map(({ url, fileName }) => ({
url,
fileName,
}));
useEffect(() => {
const fetchImages = () => {
charts.map(({ url, fileName }) => {
fetch(url)
.then((response) => response.blob())
.then(
(blob) =>
new File([blob], `${fileName}`, {
type: blob.type,
})
)
.then((file) => {
setFileImages((prev) => [...prev, file]);
});
});
};
fetchImages();
}, [state.chartsList.length]);
You can use 'convert-svg-to-png' library.
This is the npm link
Then import it:
const { convertFile } = require('convert-svg-to-png');
Then use the following code:
(async() => {
const inputFilePath = '/path/to/my-image.svg';
const outputFilePath = await convertFile(inputFilePath);
console.log(outputFilePath);
//=> "/path/to/my-image.png"
})();
Hope it works for you :)
I tried to resize or compress an image before uploading to the google cloud storage.
The upload works fine but the resizing does not seem to work.
Here is my code:
const uploadImage = async (file) => new Promise((resolve, reject) => {
let { originalname, buffer } = file
sharp(buffer)
.resize(1800, 948)
.toFormat("jpeg")
.jpeg({ quality: 80 })
.toBuffer()
const blob = bucket.file(originalname.replace(/ /g, "_"))
const blobStream = blob.createWriteStream({
resumable: false
})
blobStream.on('finish', () => {
const publicUrl = format(
`https://storage.googleapis.com/${bucket.name}/${blob.name}`
)
resolve(publicUrl)
}).on('error', () => {
reject(`Unable to upload image, something went wrong`)
})
.end(buffer)
})
I ran into the same issue with a project I was working on. After lots of trial and error I found the following solution. It might not be the most elegant, but it worked for me.
In my upload route function I created a new thumbnail image object with the original file values and passed it as the file parameter to the uploadFile function for google cloud storage.
Inside my upload image route function:
const file = req.file;
const thumbnail = {
fieldname: file.fieldname,
originalname: `thumbnail_${file.originalname}`,
encoding: file.encoding,
mimetype: file.mimetype,
buffer: await sharp(file.buffer).resize({ width: 150 }).toBuffer()
}
const uploadThumbnail = await uploadFile(thumbnail);
My google cloud storage upload file function:
const uploadFile = async (file) => new Promise((resolve, reject) => {
const gcsname = file.originalname;
const bucketFile = bucket.file(gcsname);
const stream = bucketFile.createWriteStream({
resumable: false,
metadata: {
contentType: file.mimetype
}
});
stream.on('error', (err) => {
reject(err);
});
stream.on('finish', (res) => {
resolve({
name: gcsname
});
});
stream.end(file.buffer);
});
I think the problem is with toFormat(). That function does not exist in the Docs. Can you try to remove it and check if it would work?
sharp(buffer)
.resize(1800, 948)
.jpeg({ quality: 80 })
.toBuffer()
Modify the metadata once you have finished uploading the image.
import * as admin from "firebase-admin";
import * as functions from "firebase-functions";
import { log } from "firebase-functions/logger";
import * as sharp from "sharp";
export const uploadFile = functions.https.onCall(async (data, context) => {
const bytes = data.imageData;
const bucket = admin.storage().bucket();
const buffer = Buffer.from(bytes, "base64");
const bufferSharp = await sharp(buffer)
.png()
.resize({ width: 500 })
.toBuffer();
const nombre = "IMAGE_NAME.png";
const fileName = `img/${nombre}.png`;
const fileUpload = bucket.file(fileName);
const uploadStream = fileUpload.createWriteStream();
uploadStream.on("error", async (err) => {
log("Error uploading image", err);
throw new functions.https.HttpsError("unknown", "Error uploading image");
});
uploadStream.on("finish", async () => {
await fileUpload.setMetadata({ contentType: "image/png" });
log("Upload success");
});
uploadStream.end(bufferSharp);
});
I was trying to create an API endpoint for rotating images uploaded from client side. I'm sending images as base64 type, converted from blob (from simple <input tag), as follows:
const addImageBase64 = async (fileData) => {
const file = fileData;
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = (event) => {
resolve(event.target.result);
};
reader.onerror = (err) => {
reject(err);
};
reader.readAsDataURL(file);
});
};
Then, on the server side, that's how the endpoint looks like:
app.post("/api/rotate-image", async (req, res) => {
try {
let buffer = Buffer.from(req.body.imageData, "base64"); //not working
let array = new Uint8Array(buffer); //not working
const image = await sharp(buffer)
.rotate(180)
.png({ quality: 100 })
.toBuffer();
console.log("success");
res.status(200).send({
success: true,
result: image,
});
} catch (e) {
console.warn(e);
}
});
And here, every my attempt is ending up with '[Error: Input buffer contains unsupported image format]' - either for Buffer or Uint8Array. Can anyone help me with this issue? What is the right input type for Sharp that acctually works?
Edit:
Error with logged buffer obj:
convert png image to JPG
Here is my code:
const uploadFile = ({ file, options }) =>
new Promise((resolve, reject) => {
const orignalname = file.hapi.filename;
const filename = `${moment().unix()}${generateCode(2)}${path.extname(
orignalname
)}`;
const location = `${dirName}${options.dest}/${filename}`;
checkOrCreateDir(dirName);
checkOrCreateDir(`${dirName}${options.dest}`);
const fileStream = fs.createWriteStream(location);
file.on("error", err => {
reject(err);
});
file.pipe(fileStream);
file.on("end", err => {
const fileDetails = {
fieldname: filename,
originalname: file.hapi.filename,
filename,
mimetype: file.hapi.headers["content-type"],
destination: `${options.dest}`,
path: location,
buffer: file._data
// size: fs.statSync(location).size
};
resolve(fileDetails);
});
});
I also tried easyImage and imagemagic package in node but can't got perfect output
Also using imageThumbnail package for thumbnail image
any type of image type to convert jpg format
I'm trying to upload an image using Laravel as a backend and Vue.js2 as a frontend.
Here's my code
addUser() {
let formData = new FormData();
formData.append('fullname', this.newUser.fullname);
formData.append('email', this.newUser.email);
formData.append('phone', this.newUser.phone);
formData.append('photo', this.newUser.photo);
formData.append('roles', this.newUser.roles);
formData.append('permissions', this.newUser.permissions);
axios.post('users', formData)
.then((response) => {
console.log(response);
})
.catch((error) => {
console.log(error);
});
},
onFileChange(e) {
let files = e.target.files || e.dataTransfer.files;
if (!files.length)
return;
this.createImage(files[0]);
},
createImage(file) {
let reader = new FileReader();
let vm = this;
reader.onload = (e) => {
vm.newUser.photo = e.target.result;
};
reader.readAsDataURL(file);
},
And Laravel code on a backend:
if($request->hasFile('photo')) {
return response()->json([
'success' => true,
'message' => 'Файл есть.',
'data' => $request->all()
]);
}
return response()->json([
'success' => true
]);
Finally, the html code:
<input type="file" class="filestyle" data-text="Загрузите фото" #change="onFileChange">
Unfortunately, it doesn't seem to work. File has not been found. What's the workaround?
I doubt that the image gets attached to the request sent because the line formData.append('photo', this.newUser.photo); only appends the file's temporary url to the formData due to the fact that the property photo of the newUser object was set to the temporary url of the file inside your FileReader onload method: vm.newUser.photo = e.target.result;.
You should attach the file to the formData and not the temporary url
To do that, you might want to change your createImage(file) function to:
createImage(file) {
let reader = new FileReader();
this.newUser.photo = file;
let vm = this;
reader.onload = (e) => {
vm.newUser.photo_preview = e.target.result;
};
reader.readAsDataURL(file);
},
and you can use this.newUser.photo_preview for showing the photo preview wherever you like in your view.
Hope that helps :)
Solved
I simply deleted createImage(file) method and changed onFileChange(e) method like this:
onFileChange(e) {
let files = e.target.files || e.dataTransfer.files;
if (!files.length)
return;
this.newUser.photo = files[0];
}
And everything worked perfecly. Thanks for everyone for spending time and help...)