Closed ApayRus closed 7 years ago
Now, what about removing? It is enough to just remove image from collection Images?
Yes, if you follow AWS-S3-Integration docs. This part is responsible for synced removal:
// Intercept FilesCollection's remove method to remove file from AWS:S3
const _origRemove = UserFiles.remove;
UserFiles.remove = function (search) {
const cursor = this.collection.find(search);
cursor.forEach((fileRef) => {
_.each(fileRef.versions, (vRef) => {
if (vRef && vRef.meta && vRef.meta.pipePath) {
// Remove the object from AWS:S3 first, then we will call the original FilesCollection remove
s3.deleteObject({
Bucket: s3Conf.bucket,
Key: vRef.meta.pipePath,
}, (error) => {
bound(() => {
if (error) {
console.error(error);
}
});
});
}
});
});
//remove original file from database
_origRemove.call(this, search);
};
I used some code from comments in some issue from man with same problem, because from docs didn't work:
import { Meteor } from "meteor/meteor";
import { FilesCollection } from "meteor/ostrio:files";
import { _ } from "meteor/underscore";
import { Random } from "meteor/random";
import fs from "fs";
import stream from "stream";
var s3, bound, s3Conf = {};
if (Meteor.isServer) {
import S3 from "aws-sdk/clients/s3";
s3Conf = Meteor.settings.s3 || {};
bound = Meteor.bindEnvironment((callback) => {
return callback();
});
// Create a new S3 object
s3 = new S3({
secretAccessKey: s3Conf.secret,
accessKeyId: s3Conf.key,
region: s3Conf.region,
sslEnabled: true,
httpOptions: {
timeout: 6000,
agent: false
}
});
}
var Images = new FilesCollection({
debug: false,
collectionName: "Images",
allowClientCode: true, // Disallow remove files from Client
onBeforeUpload(file) {
// Allow upload files under 10MB, and only in png/jpg/jpeg formats
if (file.size <= 1048576 && /png|jpg|jpeg|gif|svg/i.test(file.extension)) {
return true;
} else {
return 'Please upload image, with size equal or less than 1MB';
}
},
onAfterUpload(fileRef) {
var self = this;
_.each(fileRef.versions, (vRef, version) => {
const filePath = "files/" + (Random.id()) + "-" + version + "." + fileRef.extension;
s3.putObject({
ServerSideEncryption: "AES256",
StorageClass: "STANDARD",
Bucket: s3Conf.bucket,
Key: filePath,
Body: fs.createReadStream(vRef.path),
ContentType: vRef.type,
}, (error) => {
bound(() => {
if (error) {
console.error(error);
} else {
const upd = { $set: {} };
upd["$set"]["versions." + version + ".meta.pipePath"] = filePath;
self.collection.update({
_id: fileRef._id
}, upd, function(updError) {
if (updError) {
console.error(updError);
} else {
console.log("Uploaded to S3");
self.unlink(self.collection.findOne(fileRef._id), version);
}
});
}
});
});
});
},
interceptDownload(http, fileRef, version) {
let path;
if (fileRef && fileRef.versions && fileRef.versions[version] && fileRef.versions[version].meta && fileRef.versions[version].meta.pipePath) {
path = fileRef.versions[version].meta.pipePath;
}
if (path) {
const opts = {
Bucket: s3Conf.bucket,
Key: path
};
if (http.request.headers.range) {
const vRef = fileRef.versions[version];
let range = _.clone(http.request.headers.range);
const array = range.split(/bytes=([0-9]*)-([0-9]*)/);
const start = parseInt(array[1]);
let end = parseInt(array[2]);
if (isNaN(end)) {
// Request data from AWS:S3 by small chunks
end = (start + this.chunkSize) - 1;
if (end >= vRef.size) {
end = vRef.size - 1;
}
}
opts.Range = `bytes=${start}-${end}`;
http.request.headers.range = `bytes=${start}-${end}`;
}
const fileColl = this;
s3.getObject(opts, function(error) {
if (error) {
console.error(error);
if (!http.response.finished) {
http.response.end();
}
} else {
if (http.request.headers.range && this.httpResponse.headers["content-range"]) {
// Set proper range header in according to what is returned from AWS:S3
http.request.headers.range = this.httpResponse.headers["content-range"].split("/")[0].replace("bytes ", "bytes=");
}
const dataStream = new stream.PassThrough();
fileColl.serve(http, fileRef, fileRef.versions[version], version, dataStream);
dataStream.end(this.data.Body);
}
});
return true;
}
return false;
}
});
global.Images = Images;
if (Meteor.isServer) {
Meteor.publish("files.images.all", function() {
return Images.find().cursor;
});
} else {
Meteor.subscribe("files.images.all");
}
export default Images;
S3 is black box for me. Should I learn its docs? In my case images don't remove from server?
because from docs didn't work
What actually not working in the AWS S3 tutorial? Do you have errors? - if you do, we will fix it.
S3 is black box for me. Should I learn its docs?
Sure, you're better to know what you're doing.
In my case images don't remove from server?
Only from server and DB, as you don't have a hook to remove a file from S3 with s3.deleteObject()
What actually not working in the AWS S3 tutorial?
sorry, I don't remember, I discussed it here in issues about 2 months ago. finally I have found solution.
what about my previos realisation? this part with removing image was in AutoForm plugin? Now, when I don't use it , where should I paste this part of code?
What I published in prev message, it is my whole images.js collection file.
what about my previos realisation? this part with removing image was in AutoForm plugin?
AutoForm
has not relation to how do you initialize FilesCollection instance. If you take a look on mf-autoform quick start, you will see what construction new FilesCollection({/*...*/});
should be defined by you, and not handled by AutoForm
package.
Now, when I don't use it , where should I paste this part of code?
What code? As I mentioned above using AutoForm
or not using it has no relation to AWS:S3 integration - It's two separate, unrelated things.
What I published in prev message, it is my whole images.js collection file.
Well... compare it to the AWS S3 tutorial, and update with what is missing on your end.
With autoform plugin it was just few strings of code, to handle removing file.
<template name="myFilePreview">
<br />
<img src="{{link}}">
<br />
{{#if isAdmin}}
<a data-remove-file href="#">Remove</a>
{{/if}}
</template>
I'm interesting , how to make remove file without autoform. I suppose there is some small snippet, I didn't find it in demo. And don't want to read all docs (
how to make remove file without autoform
And don't want to read all docs (
Then I cannot help you, though. You should read the docs before asking a question.
Ok. Thanks. Your support is awesome!
I realized issue #7 with your help, using Sessions. Now, what about removing? It is enough to just remove image from collection Images? (I use S3 integration). Or it only clears information about image in db, but file steel exist on the server?
with AutoForm I was using this predefined template (and you can see how it looks in issue #7 , but what is good way to realize it without AutoForm, only with blaze):