Как загрузить изображения из AWS в папку в метеоре
Следующий код работает. Но он загружает только одно изображение. Я хочу, чтобы он загружал несколько изображений и, если не слишком много проблем, поместил их в папку, возможно, в папку zip. По какой-то причине он не будет загружать более одной фотографии (при загрузке дополнительных изображений в сети происходит сбой сети). И я попытался реализовать JSZip, который я настроил, но я не мог понять, как затем использовать новый объект JSZip для инициирования загрузки с сервера. Кто-нибудь может предложить какой-нибудь код или указать мне правильное направление?
Желательно, чтобы это происходило на сервере.
На клиенте:
'click #download-all-photos': function (event, template) {
Files.find({
productId: this._id
}).forEach((photo) => {
Meteor.call('get.s3.image', photo, function (error, result) {
if (error) {
console.log(error);
} else {
function _arrayBufferToBase64(buffer) {
var binary = '';
var bytes = new Uint8Array(buffer);
var len = bytes.byteLength;
for (var i = 0; i < len; i++) {
binary += String.fromCharCode(bytes[i] );
}
return window.btoa(binary);
}
let base64 = _arrayBufferToBase64(result.data);
base64 = 'data:' +result.mimeType+ ';base64,'+base64;
let link = document.createElement('a');
link.setAttribute('href', base64);
link.setAttribute('download', result.fileName);
link.click();
link.remove();
}
});
});
}
});
Сервер:
'get.s3.image': function (photo) {
let fileType = '';
let split = photo.url.split('.');
fileType = split[split.length-1];
let bucket = split[0].replace('https://', '');
var s3 = new AWS.S3({
accessKeyId: AWSAccessKeyId,
secretAccessKey: AWSSecretAccessKey
});
let split2 = photo.url.split('/');
let split3 = photo.url.split(split2[2] + '/');
let fileName = '';
fileName = split2[split2.length-1];
let key = split3[1];
let mimeType = mime.lookup(photo.url);
let fut = new Future();
s3.getObject(
{ Bucket: bucket, Key: key },
function (error, data) {
if (error) {
console.log("Failed to retrieve an object: " + error);
fut['return'](error);
throw new Meteor.Error('500', error);
} else {
console.log("Loaded " + data.ContentLength + " bytes");
fut['return']({
mimeType: mimeType,
fileName: fileName,
data: data.Body
});
}
}
);
return fut.wait();
},
Еще одна вещь, которую я попробовал, - это создание маршрута для загрузки изображения. Опять же, это работает, но я могу заставить его сделать только одно изображение. Я бы предпочел, чтобы он просматривал запрашиваемую коллекцию изображений и загружал их все в zip-папку:
Router.route('/download_file/:_id', {
name: 'download.file',
where: 'server',
action: function () {
let res = this.response;
let image = Files.findOne(this.params._id);
if (!image) {
res.writeHead(404, {'Content-Type': 'text/html'});
res.end('404: No Images Found');
return;
}
let mimeType = mime.lookup(image.url);
let fileType = '';
let split = image.url.split('.');
fileType = split[split.length-1];
let bucket = split[0].replace('https://', '');
var s3 = new AWS.S3({
accessKeyId: AWSAccessKeyId,
secretAccessKey: AWSSecretAccessKey
});
let split2 = image.url.split('/');
let split3 = image.url.split(split2[2] + '/');
let key = split3[1];
s3.getObject(
{ Bucket: bucket, Key: key },
function (error, data) {
if (error != null) {
console.log("Failed to retrieve an object: " + error);
} else {
let headers = {
'Content-Type': mimeType,
'Content-Disposition': "attachment; filename=file."+fileType
};
res.writeHead(200, headers);
res.end(data.Body, 'binary');
}
}
);
}
});
1 ответ
Казалось, я решил свою проблему! Может быть, хакерский. У меня работает JSZip. Он получает файлы от S3, а затем отправляет их клиенту для загрузки в zip-архив (загружается через saveAs()
из пакета метеора). Кажется, работает очень хорошо. Может быть, это может помочь кому-то еще.
Клиент:
'click #download-all-photos': function (event, template) {
let JSZip = require('jszip');
let zip = new JSZip();
let folder = zip.folder('photos');
let hasError = false;
let fileName = '';
if (this.mpn) fileName += this.mpn + '_';
fileName += this.productNumber;
let count = 0;
let number = Files.find({ productId: this._id }).count();
let downloaded = false;
Files.find({ productId: this._id }).forEach((photo) => {
Meteor.call('get.s3.image', photo, function (error, result) {
if (error) {
console.log(error);
} else {
folder.file(result.fileName, result.data);
count++;
if (count === number && !downloaded) {
downloaded = true;
let zipFile = zip.generate();
let base64 = 'data:application/zip;base64,'+zipFile;
fetch(base64)
.then(res => res.blob())
.then(blob => {
saveAs(blob, fileName + '.zip');
});
}
}
});
});
}
Сервер:
'get.s3.image': function (photo) {
let fileType = '';
let split = photo.url.split('.');
fileType = split[split.length-1];
let bucket = split[0].replace('https://', '');
var s3 = new AWS.S3({
accessKeyId: AWSAccessKeyId,
secretAccessKey: AWSSecretAccessKey
});
let split2 = photo.url.split('/');
let split3 = photo.url.split(split2[2] + '/');
let fileName = '';
fileName = split2[split2.length-1];
let key = split3[1];
let mimeType = mime.lookup(photo.url);
let fut = new Future();
s3.getObject(
{ Bucket: bucket, Key: key },
function (error, data) {
if (error) {
console.log("Failed to retrieve an object: " + error);
fut['return'](error);
throw new Meteor.Error('500', error);
} else {
console.log("Loaded " + data.ContentLength + " bytes");
fut['return']({
mimeType: mimeType,
fileName: fileName,
data: data.Body
});
}
}
);
return fut.wait();
},