The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →To strip EXIF location data in an Express app, never publish the uploaded file itself. Accept it with a tightly limited Multer route, decode and re-encode it with Sharp (which drops metadata by default on output), then inspect the output bytes for leftover metadata. Publish only if that check passes, and fail closed if anything throws. This guide builds that pipeline step by step, including the verification step that most tutorials skip.
Why the check must run on the output
Sharp’s output documentation says: “By default all metadata will be removed, which includes EXIF-based orientation.” That is the privacy boundary: a fresh encode, with no metadata-preserving calls, produces a file without the original’s GPS tags.
As an Amazon Associate I earn from qualifying purchases.
The trap is verification. Sharp’s metadata() reads the header of whatever it is given and, per its documentation, does not take later operations in the pipeline into account. Calling sharp(upload).metadata() tells you what the original contained, not what you are about to publish. To verify, you have to open the encoded result as a new input.
Quick wins for a faster PC:
Repair Windows errors before they cause bigger problemsFix Now →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Be clear about what this proves. The check is an application-level safeguard built on documented APIs; Sharp does not ship a complete privacy audit. It shows that, for the metadata classes you test, the specific bytes you publish do not carry them. It does not prove every container in every codec is absent under every Sharp/libvips build, so pin your dependency versions and test with real fixtures.
#1 Best Overall
- HD CAMERA WITH CLEAR VISIBILITY: Features a 1080P HD camera that lets you see inside your ear canal in real time via your smartphone
- WIDE COMPATIBILITY: Connects wirelessly to both iOS and Android devices, making it easy to monitor and clean your ears using a free app
- SOFT SILICONE EAR SPOON: Includes gentle silicone tips that are hollow and clipable, allowing safe and comfortable earwax removal without irritation
- 10-IN-1 COMPLETE KIT: Comes with multi tools including ear picks, a cleaning brush, silicone tips, and a USB charging cable for versatile ear care
- WATERPROOF LENS DESIGN: The camera lens is waterproof, ensuring durability and easy cleaning after each use
The pipeline
- Accept one file on one route, with explicit size and count limits.
- Keep the upload in memory (or a private temp location); never in a public directory.
- Let Sharp decode it, apply orientation, and re-encode to a format you allow.
- Re-open the encoded buffer and check for forbidden metadata.
- Store or serve only the verified buffer, under a server-generated name.
- On any failure, reject the upload. Never fall back to the original.
Step 1: A locked-down upload route
Multer’s documentation describes route-specific middleware and request limits, and warns against using .any() globally. Many limits are unlimited unless you set them, so configure them explicitly and note that Multer says limits help protect against denial-of-service.
import express from "express";
import multer from "multer";
const upload = multer({
storage: multer.memoryStorage(),
limits: {
fileSize: 10 * 1024 * 1024, // 10 MB; choose for your product
files: 1,
fields: 5,
parts: 6,
},
});
const app = express();
app.post("/api/images", upload.single("image"), handleUpload);
Memory storage keeps the original off disk, which simplifies cleanup, but ties peak memory to concurrent uploads times the size limit. If that is a concern, use a private temp directory and delete files in a finally block. Either way, treat originalname and mimetype as client claims: they are not evidence of what the bytes are. Do not use originalname as a storage key or in a public URL.
Rank #2
- High-end Precision Mechanical-arm Tweezer: Red Dot Award winner. Crafted from medical-grade stainless steel, Anyear2-in-1 ear wax removal tool seamlessly transitions between ear scoop and tweezing, offering exceptional quality and versatility for effective ear wax removal and foreign object retrieval.
- Revolutionary Real-time Video Consultations: Anyear ear cleaner allows real-time remote consultations with healthcare experts while also recording and observing the ear canal, minimizing the necessity for frequent hospital visits. It's affordable, user-friendly, and portable, making it an ideal solution for your family's home health needs.
- HD Stable Otoscope & Wide Compatibility: Our advanced 10-megapixel ear camera and precision gyroscope ensure clear, stable visuals, making ear cleaning easier and safer. Compatible with Tablet, Android, and iOS devices. Simply download the ISEE app, connect the device via Wifi, and start cleaning earwax.
- Versatile and Safe Tool: Designed for earwax removal and ENT examinations, including skin, scalp, and pets. Suitable for all ages, it comes with multiple attachments for maximum hygiene. Gift your loved ones the assurance of improved hearing and heightened hygiene with this premium ear care solution.
- What You Get: 1*Smart Visual Ear Tweezers, 12* Ear Pick Cover, 1*Observation Cap, 2*Alcohol Swab, 1* Type C Charging, 1* Manual. We prioritize quality, with each ear cleaner earwax removal kit undergoing manual testing to ensure the best solution for your ear care needs. Enjoy peace of mind with a 60-day refund and a 2-year warranty. If you have any questions, please don't hesitate to contact us; we'll respond within 12 hours.
Step 2: Re-encode with Sharp
Sharp recommends its default warning-level failure behavior for untrusted input, so do not loosen failOn. Let Sharp, not the declared MIME type, decide whether the file is a decodable image, then map the detected format to an allowed output.
import sharp from "sharp";
import { randomUUID } from "node:crypto";
const OUTPUT = {
jpeg: { ext: "jpg", apply: (s) => s.jpeg({ quality: 85 }) },
png: { ext: "png", apply: (s) => s.png() },
webp: { ext: "webp", apply: (s) => s.webp({ quality: 85 }) },
};
async function reencode(input) {
const meta = await sharp(input).metadata(); // input header only
const target = OUTPUT[meta.format];
if (!target) throw new Error("Unsupported image format");
const pipeline = sharp(input).rotate(); // bake EXIF orientation into pixels
const buffer = await target.apply(pipeline).toBuffer();
return { buffer, ext: target.ext };
}
Two details matter here:
- Orientation. Sharp’s default stripping removes the EXIF orientation tag too. Calling
.rotate()with no arguments applies the orientation to the pixels first, so phone photos taken in portrait do not suddenly appear sideways. Test this with an orientation-tagged fixture. - What not to call. If the goal is removal, do not use
keepMetadata(),withMetadata(),keepExif()or any metadata-writing helper anywhere in the chain.
Step 3: Verify the encoded bytes
Open the result as a brand-new input and fail on any metadata class your policy forbids. The first pass below uses Sharp itself; its metadata() can report EXIF, ICC, IPTC and XMP blocks when present in the header it reads.
Rank #3
async function assertClean(buffer) {
const m = await sharp(buffer).metadata();
const found = [];
if (m.exif) found.push("exif");
if (m.iptc) found.push("iptc");
if (m.xmp || m.xmpAsString) found.push("xmp");
if (m.tifftagPhotoshop) found.push("photoshop");
if (m.comments && m.comments.length) found.push("comments");
if (m.icc) found.push("icc"); // include only if your policy forbids profiles
if (found.length) {
throw new Error("Forbidden metadata after re-encode: " + found.join(", "));
}
}
Decide the policy deliberately. GPS lives in EXIF, so the exif check is the essential one for location privacy. Whether an ICC colour profile counts as forbidden is a product decision: it is not location data, and a missing profile can alter colour rendering for wide-gamut images, so many sites allow it. Keep the icc line only if your promise is “no embedded profiles at all”. Note that the field names above are those Sharp exposes in recent versions; confirm them against the version you install.
Add an independent parser for stronger assurance
Using Sharp to check Sharp shares libvips’ view of the file. For a stronger guarantee, also run the output buffer through a separate EXIF/metadata parsing library and assert that it finds no GPS fields (and no EXIF at all, if that is your policy). A parse error should count as a failure, not a pass. Which parser you pick matters less than the principle that it reads the final buffer.
Rank #4
- Ultra-bright Illumination for Precise Visualization of Dirt: For ultra-bright visualization and precise ear wax targeting, the innovative integration of a 6LED high-intensity lighting system, combined with an HD ear camera, illuminates even the most concealed corners of the ear canal, revealing every detail of ear wax on the smart device screen with clarity.
- Skin-friendly material:Crafted from medical-grade skin-friendly materials, the ear cleaner with camera gently safeguards the ear canal. The specially designed white medical silicone ear scoop is soft yet resilient, fitting snugly to the contours of the ear canal, gently removing ear wax while providing comprehensive protection to delicate ear tissues, effectively mitigating risks of scratches and inflammation, suitable for both children and the elderly to enjoy comfortable ear care.
- Convenient WiFi control: With stable WiFi connectivity, real-time transmission of images is achieved without delay, precisely guiding the ear wax removal process to ensure every cleaning strike is accurate, making deep cleaning effortless with the ear wax removal tool camera,enabling smooth switching of lighting, camera functions, and modes with a single press.
- Multifunctional integrated:As a multifunctional all-in-one device, it fulfills diverse needs by integrating ear wax removal, ear canal photography, videography, and health tracking. It allows for the instant saving of ear canal images and tracks changes in ear health. Equipped with multiple ear scoop heads, it accommodates various ear canal sizes, making it a shared ear cleaning kit for the whole family, catering to all ear cleaning scenarios.
- Wide compatibility: it fulfills diverse needs by integrating ear wax removal, ear canal photography, videography, and health tracking. It allows for the instant saving of ear canal images and tracks changes in ear health. Equipped with multiple ear scoop heads, it accommodates various ear canal sizes, making it a shared ear cleaning kit for the whole family, catering to all ear cleaning scenarios.
Step 4: Wire it together and fail closed
async function handleUpload(req, res) {
if (!req.file) return res.status(400).json({ error: "No image uploaded" });
try {
const { buffer, ext } = await reencode(req.file.buffer);
await assertClean(buffer);
const name = randomUUID() + "." + ext; // server-generated, never originalname
await saveToPublicStorage(name, buffer); // your disk, S3-compatible bucket, etc.
return res.status(201).json({ url: "/images/" + name });
} catch (err) {
console.error("image rejected", err.message); // log reason, not file contents
return res.status(422).json({ error: "Image could not be processed" });
}
}
app.use((err, req, res, next) => {
if (err instanceof multer.MulterError) {
return res.status(413).json({ error: "Upload rejected: " + err.code });
}
next(err);
});
The important property is what is absent: no branch publishes req.file.buffer. If decoding fails, the format is unsupported, the output still has metadata, or storage throws, the client gets an error and nothing public is written.
Free tools Windows power users keep installed
One-click scans. No signup required.
Test fixtures to keep in your repo
Because behavior can change across Sharp and libvips versions, make the guarantee a test, not a belief. Pin the Sharp version in your lockfile and run these on every upgrade, for each format you accept:
Best Value
- 【No App Needed】Skip downloads, registration, and complicated setup. Simply remove the ear cleaner from the charging case, and it automatically powers on and connects to the built-in screen within seconds. Easy to operate with multiple language options for a smooth user experience.
- 【1080P HD Camera】Enjoy a crystal-clear view with the 1080P HD ear camera, 360° wide-angle lens, and 6 LED lights. The built-in display lets you see every detail in real time, making everyday ear cleaning easier and more precise. Save photos and videos to the included TF card for personal reference.
- 【Comfortable Cleaning】The ultra-slim camera tip and soft silicone covers are designed for a smooth and comfortable cleaning experience. Multiple replacement tips make it easy for everyday family use while helping keep the ear cleaner hygienic.
- 【Long Battery Life】The rechargeable 230mAh ear cleaner provides up to 90 minutes of continuous use, while the 2000mAh charging case offers additional power and convenient storage, making it ideal for home or travel.
- 【Designed for Everyday Use】Lightweight, portable, and easy to use, this ear cleaning kit is suitable for daily personal care at home or while traveling. The waterproof camera lens is easy to clean after each use. (Do not immerse the entire device in water.)
| Fixture | What it proves |
|---|---|
| Phone JPEG with GPS EXIF | Output has no EXIF; independent parser finds no GPS |
| JPEG with orientation tag (for example a rotated portrait) | Output dimensions and appearance are upright with no orientation tag |
| File with XMP or IPTC but no EXIF | Non-EXIF containers are also gone, or the check rejects |
| File with embedded ICC profile | Behavior matches your stated profile policy |
| Image with no metadata | Pipeline passes cleanly; no false rejections |
| Renamed non-image (for example a text file called photo.jpg) | Decode fails and nothing is published |
| File over the size limit | Multer rejects before processing |
Also include a negative control: deliberately build a pipeline that calls withMetadata() in a test and confirm that assertClean rejects it. That proves the verifier can actually fail.
Other hardening points
- Animated or multi-page inputs. Decide whether to accept them. The pipeline above treats input as a single image; if you allow animated formats you need to configure and test that path separately.
- Decompression bombs. A small file can decode to enormous pixel dimensions. Keep Sharp’s input pixel limit in place rather than disabling it, and consider rejecting images above dimensions your product needs.
- Private originals. Do not write the upload to a statically served directory, even briefly.
- Existing images. This pipeline protects new uploads. Images already published still contain whatever they contained; re-process them through the same function and replace them.
- Metadata outside the file. Filenames, captions and form fields submitted alongside the image can also leak location. Validate or discard them separately.
The Multer and Sharp behavior described here comes from their official project documentation, accessed in October 2026. Sharp’s API evolves, so confirm option and field names against the exact version and libvips build you deploy.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




