fix: #7597, fix progress bar of cover/profile uploads

send big cover images in chunks
v1.18.x
Barış Soner Uşaklı 4 years ago
parent a1b658d945
commit 7e867cf95e

@ -106,14 +106,14 @@ define('pictureCropper', ['cropper'], function (Cropper) {
return; return;
} }
cropperModal.find('#upload-progress-bar').css('width', '100%'); cropperModal.find('#upload-progress-bar').css('width', '0%');
cropperModal.find('#upload-progress-box').show().removeClass('hide'); cropperModal.find('#upload-progress-box').show().removeClass('hide');
var socketData = {}; socketUpload({
socketData[data.paramName] = data.paramValue; data: data,
socketData.imageData = imageData; imageData: imageData,
progressBarEl: cropperModal.find('#upload-progress-bar'),
socket.emit(data.socketMethod, socketData, function (err, imageData) { }, function (err, result) {
if (err) { if (err) {
cropperModal.find('#upload-progress-box').hide(); cropperModal.find('#upload-progress-box').hide();
cropperModal.find('.upload-btn').removeClass('disabled'); cropperModal.find('.upload-btn').removeClass('disabled');
@ -121,7 +121,7 @@ define('pictureCropper', ['cropper'], function (Cropper) {
return app.alertError(err.message); return app.alertError(err.message);
} }
callback(imageData.url); callback(result.url);
cropperModal.modal('hide'); cropperModal.modal('hide');
}); });
}); });
@ -143,6 +143,36 @@ define('pictureCropper', ['cropper'], function (Cropper) {
}); });
}; };
function socketUpload(params, callback) {
var socketData = {};
socketData[params.data.paramName] = params.data.paramValue;
socketData.method = params.data.socketMethod;
socketData.size = params.imageData.length;
socketData.progress = 0;
var chunkSize = 100000;
function doUpload() {
var chunk = params.imageData.slice(socketData.progress, socketData.progress + chunkSize);
socket.emit('uploads.upload', {
chunk: chunk,
params: socketData,
}, function (err, result) {
if (err) {
return app.alertError(err);
}
if (socketData.progress + chunkSize < socketData.size) {
socketData.progress += chunk.length;
params.progressBarEl.css('width', (socketData.progress / socketData.size * 100).toFixed(2) + '%');
return setTimeout(doUpload, 100);
}
params.progressBarEl.css('width', '100%');
callback(null, result);
});
}
doUpload();
}
function checkCORS(cropperTool, data) { function checkCORS(cropperTool, data) {
var imageData; var imageData;
try { try {
@ -177,7 +207,7 @@ define('pictureCropper', ['cropper'], function (Cropper) {
var file = fileInput[0].files[0]; var file = fileInput[0].files[0];
var fileSize = data.hasOwnProperty('fileSize') && data.fileSize !== undefined ? parseInt(data.fileSize, 10) : false; var fileSize = data.hasOwnProperty('fileSize') && data.fileSize !== undefined ? parseInt(data.fileSize, 10) : false;
if (fileSize && file.size > fileSize * 1024) { if (fileSize && file.size > fileSize * 1024) {
return app.alertError('[[error:file-too-big, ' + fileSize + ']]'); return showAlert('error', '[[error:file-too-big, ' + fileSize + ']]');
} }
if (file.name.endsWith('.gif')) { if (file.name.endsWith('.gif')) {

@ -69,6 +69,14 @@ function onConnection(socket) {
socket.on('*', function (payload) { socket.on('*', function (payload) {
onMessage(socket, payload); onMessage(socket, payload);
}); });
socket.on('disconnect', function () {
onDisconnect(socket);
});
}
function onDisconnect(socket) {
require('./uploads').clear(socket.id);
} }
function onConnect(socket) { function onConnect(socket) {
@ -148,7 +156,8 @@ async function onMessage(socket, payload) {
function requireModules() { function requireModules() {
var modules = ['admin', 'categories', 'groups', 'meta', 'modules', var modules = ['admin', 'categories', 'groups', 'meta', 'modules',
'notifications', 'plugins', 'posts', 'topics', 'user', 'blacklist', 'flags', 'notifications', 'plugins', 'posts', 'topics', 'user', 'blacklist',
'flags', 'uploads',
]; ];
modules.forEach(function (module) { modules.forEach(function (module) {

@ -0,0 +1,52 @@
'use strict';
const socketUser = require('./user');
const socketGroup = require('./groups');
const image = require('../image');
const meta = require('../meta');
const inProgress = {};
const uploads = module.exports;
uploads.upload = async function (socket, data) {
const methodToFunc = {
'user.uploadCroppedPicture': socketUser.uploadCroppedPicture,
'user.updateCover': socketUser.updateCover,
'groups.cover.update': socketGroup.cover.update,
};
if (!data || !data.chunk || !data.params || !data.params.method || !methodToFunc[data.params.method]) {
throw new Error('[[error:invalid-data]]');
}
inProgress[socket.id] = inProgress[socket.id] || {};
const socketUploads = inProgress[socket.id];
const method = data.params.method;
socketUploads[method] = socketUploads[method] || { imageData: '' };
socketUploads[method].imageData += data.chunk;
try {
const maxSize = data.params.method === 'user.uploadCroppedPicture' ?
meta.config.maximumProfileImageSize : meta.config.maximumCoverImageSize;
const size = image.sizeFromBase64(socketUploads[method].imageData);
if (size > maxSize * 1024) {
throw new Error('[[error:file-too-big, ' + maxSize + ']]');
}
if (socketUploads[method].imageData.length < data.params.size) {
return;
}
data.params.imageData = socketUploads[method].imageData;
const result = await methodToFunc[data.params.method](socket, data.params);
delete socketUploads[method];
return result;
} catch (err) {
delete inProgress[socket.id];
throw err;
}
};
uploads.clear = function (sid) {
delete inProgress[sid];
};
Loading…
Cancel
Save