From d491357b25ffb95e8230dea5552bdf7a4962301c Mon Sep 17 00:00:00 2001 From: bit-barron Date: Tue, 24 Sep 2024 19:55:41 +0200 Subject: [PATCH] asd --- server/src/app.controller.ts | 88 +++++++++++++++++++---------------- web/src/components/images.tsx | 20 +++----- 2 files changed, 55 insertions(+), 53 deletions(-) diff --git a/server/src/app.controller.ts b/server/src/app.controller.ts index ddf11cd..01bc2fd 100644 --- a/server/src/app.controller.ts +++ b/server/src/app.controller.ts @@ -1,7 +1,6 @@ import { Body, Controller, - Get, HttpException, HttpStatus, Post, @@ -13,7 +12,7 @@ import ffmpeg from 'fluent-ffmpeg'; import fs from 'fs'; import JSZip from 'jszip'; import path from 'path'; -import sharp from 'sharp'; +import sharp, { FormatEnum } from 'sharp'; import { AppService } from './app.service'; interface Image { @@ -22,17 +21,12 @@ interface Image { } interface Video { - // Add properties for Video interface if needed + // Define the structure of your Video type here } @Controller('api') export class AppController { - constructor(private readonly appService: AppService) {} - - @Get('hello') - async getHello() { - return 'Hello World!'; - } + constructor(private readonly appService: AppService) {}z @Post('imgs') async getImgUrl( @@ -41,61 +35,62 @@ export class AppController { ) { try { const { images, format } = payload; - console.log('Received request with format:', format); + console.log(images, format); - if (format === 'original' && images.length === 1) { - // Handle single original image download - const image = images[0]; - const response = await axios.get(image.url, { - responseType: 'arraybuffer', - }); - const imageBuffer = Buffer.from(response.data); - const contentType = response.headers['content-type']; - const name = new URL(image.url).pathname.split('/').pop() || 'image'; - - reply - .header('Content-Type', contentType) - .header('Content-Disposition', `attachment; filename=${name}`) - .send(imageBuffer); - - console.log('Single original image sent successfully'); - return 'Image processed successfully'; + if (format !== 'original' && !this.isValidFormat(format)) { + throw new HttpException( + 'Invalid format specified', + HttpStatus.BAD_REQUEST, + ); } + const imagePath = path.join(path.resolve(), 'images'); + fs.mkdirSync(imagePath, { recursive: true }); + const zip = new JSZip(); for (const image of images) { - const name = new URL(image.url).pathname.split('/').pop() || 'image'; + const name = new URL(image.url).pathname.split('/').slice(-1)[0]; + const imageType = image.headers + ?.find((header) => header.name.toLowerCase() === 'content-type') + ?.value.replace('image/', ''); + const response = await axios.get(image.url, { responseType: 'arraybuffer', }); - const imageBuffer = Buffer.from(response.data); - - const contentType = response.headers['content-type']; - console.log(`Processing image: ${name}, Content-Type: ${contentType}`); + const imageBuffer = Buffer.from(response.data, 'binary'); if (format === 'original') { - console.log(`Adding original image: ${name}, type: ${contentType}`); - zip.file(name, imageBuffer, { binary: true }); + // Don't convert, use original image data + zip.file(name, imageBuffer); } else { let sharpInstance = sharp(imageBuffer); - sharpInstance = sharpInstance.toFormat(format as any); + + if (format === 'heif') { + sharpInstance = sharpInstance.heif({ quality: 80 }); + } else { + sharpInstance = sharpInstance.toFormat(format as keyof FormatEnum); + } + const processedImage = await sharpInstance.toBuffer(); - console.log(`Adding converted image: ${name}.${format}`); - zip.file(`${name}.${format}`, processedImage, { binary: true }); + zip.file(`${name}.${format}`, processedImage); } } const zipBuffer = await zip.generateAsync({ type: 'nodebuffer' }); - console.log('ZIP file size:', zipBuffer.length, 'bytes'); + + const zipFileName = path.join(imagePath, `images.zip`); + fs.writeFileSync(zipFileName, zipBuffer); reply .header('Content-Type', 'application/zip') .header('Content-Disposition', `attachment; filename=images.zip`) .send(zipBuffer); - console.log('Response sent successfully'); - return 'Images processed successfully'; + // Cleanup: Remove the zip file after sending + fs.unlinkSync(zipFileName); + + return zipFileName; } catch (error) { console.error('Error processing images:', error); throw new HttpException( @@ -105,6 +100,19 @@ export class AppController { } } + private isValidFormat(format: string): boolean { + const validFormats = [ + 'original', + 'jpeg', + 'png', + 'webp', + 'avif', + 'heif', + 'tiff', + ]; + return validFormats.includes(format.toLowerCase()); + } + @Post('videos') async getVideoUrl( @Body() payload: { videos: Video[]; format: string }, diff --git a/web/src/components/images.tsx b/web/src/components/images.tsx index 8e1f519..ba6eac6 100644 --- a/web/src/components/images.tsx +++ b/web/src/components/images.tsx @@ -26,9 +26,7 @@ export const Images: React.FC = () => { chrome.storage.local.get(tabId.toString(), (items) => { const requests = (items[tabId.toString()] as ImageDetails[]) || []; - const imgs = requests.filter( - ({ type }) => type === "image" || type === "media" - ); + const imgs = requests.filter(({ type }) => type === "image" || type === "media"); const uniqueImages = [ ...new Map(imgs.map((item) => [item.url, item])).values(), @@ -37,12 +35,11 @@ export const Images: React.FC = () => { const imagePromises = uniqueImages.map(({ url }) => { return new Promise((resolve) => { const img = new Image(); - img.onload = () => - resolve({ - url: img.src, - height: img.height, - isGif: url.toLowerCase().endsWith(".gif"), - }); + img.onload = () => resolve({ + url: img.src, + height: img.height, + isGif: url.toLowerCase().endsWith('.gif') + }); img.onerror = () => resolve({ url, height: 0, isGif: false }); img.src = url; }); @@ -98,10 +95,7 @@ export const Images: React.FC = () => {
{images.length === 0 ? ( - <> -
No images found
-

Video Capturing is still in BETA

- +
No images found
) : (