fix img upload from url, revert webp

This commit is contained in:
lesion 2022-05-03 12:08:10 +02:00
parent f675ce7f93
commit f6797e15a7
No known key found for this signature in database
GPG key ID: 352918250B012177
5 changed files with 77 additions and 99 deletions

View file

@ -1,16 +1,14 @@
<template>
<figure :class='{ thumb, img: true }'
<div :class='{ thumb, img: true }'
:height="height" :width="width"
:style="backgroundPreview">
<picture>
<source :srcset="srcset" type='image/webp' />
<img
v-if='media'
:class='{ "u-featured": true, loading }'
:alt='media.name' :loading='lazy?"lazy":"eager"'
:src="src"
:srcset="srcset"
itemprop="image"
:height="height" :width="width"
:style="{ 'object-position': thumbnailPosition }"
@ -18,10 +16,8 @@
<img v-else-if='!media && thumb' class='thumb' src="noimg.svg" alt=''>
</picture>
</figure>
</div>
</template>
<script>
@ -43,6 +39,10 @@ export default {
backgroundImage: "url('data:image/png;base64," + this.media.preview + "')" }
}
},
srcset () {
if (this.thumb) return ''
return `/media/thumb/${this.media.url} 500w, /media/${this.media.url} 1200w`
},
media () {
return this.event.media[0]
},
@ -54,15 +54,12 @@ export default {
},
src () {
if (this.media) {
return '/media/' + (this.thumb ? 'thumb/' : '') + this.media.url
return '/media/thumb/' + this.media.url
}
if (this.thumb) {
return '/noimg.svg'
}
},
srcset () {
return this.src.replace(/.jpg$/, '.webp')
},
thumbnailPosition () {
if (this.media.focalpoint) {
const focalpoint = this.media.focalpoint
@ -90,11 +87,12 @@ export default {
}
.img img {
display: flex;
width: 100%;
max-width: 100%;
height: auto;
overflow: hidden;
transition: opacity 1s;
transition: opacity .5s;
opacity: 1;
background-size: 100%;
}
@ -108,12 +106,7 @@ export default {
aspect-ratio: 1.7778;
}
.img picture {
width: 100%;
display: flex;
}
.img picture img.loading {
.img img.loading {
opacity: 0;
}

View file

@ -8,7 +8,6 @@ const linkifyHtml = require('linkify-html')
const Sequelize = require('sequelize')
const dayjs = require('dayjs')
const helpers = require('../../helpers')
const settingsController = require('./settings')
const Event = require('../models/event')
const Resource = require('../models/resource')
@ -290,7 +289,7 @@ const eventController = {
res.sendStatus(200)
},
async isAnonEventAllowed (req, res, next) {
async isAnonEventAllowed (_req, res, next) {
if (!res.locals.settings.allow_anon_event) {
return res.sendStatus(403)
}
@ -317,7 +316,7 @@ const eventController = {
const eventDetails = {
title: body.title,
// remove html tags
// sanitize and linkify html
description: helpers.sanitizeHTML(linkifyHtml(body.description || '')),
multidate: body.multidate,
start_datetime: body.start_datetime,
@ -328,17 +327,17 @@ const eventController = {
}
if (req.file || body.image_url) {
let url
if (req.file) {
url = req.file.filename
} else {
url = await helpers.getImageFromURL(body.image_url)
if (body.image_url) {
req.file = await helpers.getImageFromURL(body.image_url)
}
let focalpoint = body.image_focalpoint ? body.image_focalpoint.split(',') : ['0', '0']
focalpoint = [parseFloat(focalpoint[0]).toFixed(2), parseFloat(focalpoint[1]).toFixed(2)]
eventDetails.media = [{
url,
url: req.file.filename,
preview: req.file.preview,
height: req.file.height,
width: req.file.width,
name: body.image_name || body.title || '',
focalpoint: [parseFloat(focalpoint[0]), parseFloat(focalpoint[1])]
}]
@ -405,41 +404,39 @@ const eventController = {
const recurrent = body.recurrent ? JSON.parse(body.recurrent) : null
const eventDetails = {
title: body.title,
// remove html tags
description: helpers.sanitizeHTML(linkifyHtml(body.description, { target: '_blank' })),
title: body.title || event.title,
// sanitize and linkify html
description: helpers.sanitizeHTML(linkifyHtml(body.description, { target: '_blank' })) || event.description,
multidate: body.multidate,
start_datetime: body.start_datetime,
end_datetime: body.end_datetime,
recurrent
}
// remove old media in case a new one is uploaded
if ((req.file || /^https?:\/\//.test(body.image_url)) && !event.recurrent && event.media && event.media.length) {
const old_path = path.resolve(config.upload_path, event.media[0].url)
const old_thumb_path = path.resolve(config.upload_path, 'thumb', event.media[0].url)
try {
const old_path = path.resolve(config.upload_path, event.media[0].url)
const old_thumb_path = path.resolve(config.upload_path, 'thumb', event.media[0].url)
fs.unlinkSync(old_path)
fs.unlinkSync(old_thumb_path)
} catch (e) {
log.info(e.toString())
}
}
let url
if (req.file) {
url = req.file.filename
} else if (body.image_url) {
if (/^https?:\/\//.test(body.image_url)) {
url = await helpers.getImageFromURL(body.image_url)
} else {
url = body.image_url
}
}
if (url && !event.recurrent) {
if (req.file || body.image_url) {
if (body.image_url) {
req.file = await helpers.getImageFromURL(body.image_url)
}
const focalpoint = body.image_focalpoint ? body.image_focalpoint.split(',') : ['0', '0']
eventDetails.media = [{
url,
name: body.image_name || '',
url: req.file.filename,
preview: req.file?.preview,
height: req.file?.height,
width: req.file?.width,
name: body.image_name || body.title || '',
focalpoint: [parseFloat(focalpoint[0].slice(0, 6)), parseFloat(focalpoint[1].slice(0, 6))]
}]
} else {
@ -481,9 +478,9 @@ const eventController = {
// check if event is mine (or user is admin)
if (event && (res.locals.user.is_admin || res.locals.user.id === event.userId)) {
if (event.media && event.media.length && !event.recurrent) {
const old_path = path.join(config.upload_path, event.media[0].url)
const old_thumb_path = path.join(config.upload_path, 'thumb', event.media[0].url)
try {
const old_path = path.join(config.upload_path, event.media[0].url)
const old_thumb_path = path.join(config.upload_path, 'thumb', event.media[0].url)
fs.unlinkSync(old_thumb_path)
fs.unlinkSync(old_path)
} catch (e) {

View file

@ -15,13 +15,11 @@ const DiskStorage = {
const filename = crypto.randomBytes(16).toString('hex')
const sharpStream = sharp({ failOnError: true })
const promises = [
sharpStream.clone().resize(500, null, { withoutEnlargement: true }).jpeg({ quality: 90, mozjpeg: true }).toFile(path.resolve(config.upload_path, 'thumb', filename + '.jpg')),
sharpStream.clone().resize(500).webp({ quality: 90, alphaQuality: 0, effort: 6 }).toFile(path.resolve(config.upload_path, 'thumb', filename + '.webp')),
sharpStream.clone().resize(1200, null, { withoutEnlargement: true } ).jpeg({ quality: 98, mozjpeg: true }).toFile(path.resolve(config.upload_path, filename + '.jpg')),
sharpStream.clone().resize(1200).webp({ quality: 98, alphaQuality: 0, effor: 6 }).toFile(path.resolve(config.upload_path, filename + '.webp')),
sharpStream.clone().resize(500, null, { withoutEnlargement: true }).jpeg({ effort: 6, mozjpeg: true }).toFile(path.resolve(config.upload_path, 'thumb', filename + '.jpg')),
sharpStream.clone().resize(1200, null, { withoutEnlargement: true } ).jpeg({ quality: 95, effort: 6, mozjpeg: true}).toFile(path.resolve(config.upload_path, filename + '.jpg')),
sharpStream.clone()
.resize(6)
.png({ quality: 20, palette: true, alphaQuality: 0, effort: 6})
.resize(5)
.png({ quality: 10, palette: true, effort: 6})
.toBuffer()
.then(buffer => buffer.toString('base64'))
]
@ -29,9 +27,8 @@ const DiskStorage = {
file.stream.pipe(sharpStream)
Promise.all(promises)
.then(res => {
const info = res[2]
const preview = res[4]
console.error(preview)
const info = res[1]
const preview = res[2]
cb(null, {
destination: config.upload_path,
filename: filename + '.jpg',

View file

@ -7,7 +7,6 @@ const dayjs = require('dayjs')
const config = require('./config')
const log = require('./log')
const pkg = require('../package.json')
const fs = require('fs')
const path = require('path')
const sharp = require('sharp')
const axios = require('axios')
@ -122,41 +121,41 @@ module.exports = {
if(!/^https?:\/\//.test(url)) {
throw Error('Hacking attempt?')
}
const filename = crypto.randomBytes(16).toString('hex') + '.jpg'
const finalPath = path.resolve(config.upload_path, filename)
const thumbPath = path.resolve(config.upload_path, 'thumb', filename)
const outStream = fs.createWriteStream(finalPath)
const thumbStream = fs.createWriteStream(thumbPath)
const resizer = sharp().resize(1200).jpeg({ quality: 95 })
const thumbnailer = sharp().resize(400).jpeg({ quality: 90 })
const filename = crypto.randomBytes(16).toString('hex')
const sharpStream = sharp({ failOnError: true })
const promises = [
sharpStream.clone().resize(500, null, { withoutEnlargement: true }).jpeg({ effort: 6, mozjpeg: true }).toFile(path.resolve(config.upload_path, 'thumb', filename + '.jpg')),
sharpStream.clone().resize(1200, null, { withoutEnlargement: true } ).jpeg({effort: 6, mozjpeg: true}).toFile(path.resolve(config.upload_path, filename + '.jpg')),
sharpStream.clone()
.resize(5)
.png({ quality: 10, palette: true, effort: 6})
.toBuffer()
.then(buffer => buffer.toString('base64'))
]
const response = await axios({ method: 'GET', url, responseType: 'stream' })
const response = await axios({ method: 'GET', url: encodeURI(url), responseType: 'stream' })
return new Promise((resolve, reject) => {
let onError = false
const err = e => {
if (onError) {
return
response.data.pipe(sharpStream)
return Promise.all(promises)
.then(res => {
const info = res[1]
const preview = res[2]
return {
destination: config.upload_path,
filename: filename + '.jpg',
path: path.resolve(config.upload_path, filename + '.jpg'),
height: info.height,
width: info.width,
size: info.size,
preview
}
onError = true
reject(e)
}
response.data
.pipe(thumbnailer)
.on('error', err)
.pipe(thumbStream)
.on('error', err)
response.data
.pipe(resizer)
.on('error', err)
.pipe(outStream)
.on('error', err)
outStream.on('finish', () => resolve(filename))
})
})
.catch(err => {
log.error(err)
req.err = err
cb(null)
})
},
/**

View file

@ -32,12 +32,8 @@
})
}
function thumbnail(event, format) {
const imgPath = event.media[0].url
if (format === 'webp') {
return `${baseurl}/media/thumb/${imgPath.replace(/.jpg$/, '.webp')}`
}
return `${baseurl}/media/thumb/${imgPath}`
function thumbnail(event) {
return `${baseurl}/media/thumb/${event.media[0].url}`
}
function position(event) {
@ -53,11 +49,7 @@
{#if event}
<a href='{baseurl}/event/{event.slug || event.id}' class='card' target='_blank'>
{#if event.media.length}
<picture>
<source srcset="{thumbnail(event, 'webp')}" type='image/webp' />
<img src="{thumbnail(event)}" alt="{event.media[0].name}" style="object-position: {position(event)}; aspect-ratio=1.7778;">
</picture>
<img src="{thumbnail(event)}" alt="{event.media[0].name}" style="object-position: {position(event)}; aspect-ratio=1.7778;">
{/if}
<div class="container">
<strong>{event.title}</strong>