/* html */
<template name="uploadForm2">
{{#with currentUpload}}
Uploading <b>{{file.name}}</b>:
<span id="progress">{{progress.get}}%</span>
{{else}}
<input id="fileInput" type="file" />
<p><small>Upload file in <code>jpeg</code> or <code>png</code> format, with size less or equal to 10MB</small></p>
{{/with}}
</template>
<template name="uploadedFiles2">
{{#if uploadedFiles.count}}
<ul>
{{#each uploadedFiles.each}}
<li>
<a href="{{link}}?download=true" download="{{name}}">{{name}}</a>
<img src="{{link}}" alt="{{name}}" />
<a class="js-remove btn">Remove</a>
</li>
{{/each}}
</ul>
{{else}}
<div>No files uploaded, yet</div>
{{/if}}
</template>
/* .js */
import { Template } from 'meteor/templating';
import { ReactiveVar } from 'meteor/reactive-var';
import { Collections } from '../../api/images/images.js';
import './file-upload-page.html';
Template.uploadForm2.onCreated(function fileUploadPageOnCreated() {
this.currentUpload = new ReactiveVar(false);
this.autorun(() => {
this.subscribe('files.images.all');
});
});
Template.uploadedFiles2.helpers({
uploadedFiles: function () {
return Collections.files.find();
},
});
Template.uploadedFiles2.events({
'click .js-remove': function (e, template) {
this.remove(function (error) {
if (error) {
console.error('File(s) is not removed!', error);
}
});
}
});
Template.uploadForm2.helpers({
currentUpload: function () {
return Template.instance().currentUpload.get();
}
});
Template.uploadForm2.events({
'change #fileInput': function (e, template) {
if (e.currentTarget.files && e.currentTarget.files[0]) {
// We upload only one file, in case
// there was multiple files selected
let file = e.currentTarget.files[0];
if (file) {
let uploadInstance = Collections.files.insert({
file: file,
streams: 'dynamic',
chunkSize: 'dynamic'
}, false);
uploadInstance.on('start', function() {
template.currentUpload.set(this);
});
uploadInstance.on('end', function(error, fileObj) {
if (error) {
alert('Error during upload: ' + error.reason);
} else {
alert('File "' + fileObj.name + '" successfully uploaded');
}
template.currentUpload.set(false);
});
uploadInstance.start();
}
}
},
});
/*server */
import { FilesCollection } from 'meteor/ostrio:files';
var Dropbox, Request, bound, client, fs = {};
if (Meteor.isServer) {
Dropbox = Npm.require('dropbox');
Request = Npm.require('request');
fs = Npm.require('fs');
bound = Meteor.bindEnvironment(function(callback) {
return callback();
});
client = new Dropbox.Client({
key: 'xxxx',
secret: 'xxxx',
token: 'xxxx',
});
}
const Collections = {};
Collections.files = new FilesCollection({
debug: true, // Change to `true` for debugging
throttle: false,
storagePath: 'assets/app/uploads/uploadedFiles',
collectionName: 'uploadedFiles',
allowClientCode: true,
onAfterUpload: function(fileRef) {
// In onAfterUpload callback we will move file to DropBox
var self = this;
var makeUrl = function(stat, fileRef, version, triesUrl) {
if (triesUrl == null) {
triesUrl = 0;
}
client.makeUrl(stat.path, {
long: true,
downloadHack: true
}, function(error, xml) {
// Store downloadable link in file's meta object
bound(function() {
if (error) {
if (triesUrl < 10) {
Meteor.setTimeout(function() {
makeUrl(stat, fileRef, version, ++triesUrl);
}, 2048);
} else {
console.error(error, {
triesUrl: triesUrl
});
}
} else if (xml) {
var upd = {
$set: {}
};
upd['$set']["versions." + version + ".meta.pipeFrom"] = xml.url;
upd['$set']["versions." + version + ".meta.pipePath"] = stat.path;
self.collection.update({
_id: fileRef._id
}, upd, function(error) {
if (error) {
console.error(error);
} else {
// Unlink original files from FS
// after successful upload to DropBox
self.unlink(self.collection.findOne(fileRef._id), version);
}
});
} else {
if (triesUrl < 10) {
Meteor.setTimeout(function() {
makeUrl(stat, fileRef, version, ++triesUrl);
}, 2048);
} else {
console.error("client.makeUrl doesn't returns xml", {
triesUrl: triesUrl
});
}
}
});
});
};
var writeToDB = function(fileRef, version, data, triesSend) {
// DropBox already uses random URLs
// No need to use random file names
if (triesSend == null) {
triesSend = 0;
}
client.writeFile(fileRef._id + "-" + version + "." + fileRef.extension, data, function(error, stat) {
bound(function() {
if (error) {
if (triesSend < 10) {
Meteor.setTimeout(function() {
writeToDB(fileRef, version, data, ++triesSend);
}, 2048);
} else {
console.error(error, {
triesSend: triesSend
});
}
} else {
// Generate downloadable link
makeUrl(stat, fileRef, version);
}
});
});
};
var readFile = function(fileRef, vRef, version, triesRead) {
if (triesRead == null) {
triesRead = 0;
}
fs.readFile(vRef.path, function(error, data) {
bound(function() {
if (error) {
if (triesRead < 10) {
readFile(fileRef, vRef, version, ++triesRead);
} else {
console.error(error);
}
} else {
writeToDB(fileRef, version, data);
}
});
});
};
var sendToStorage = function(fileRef) {
_.each(fileRef.versions, function(vRef, version) {
readFile(fileRef, vRef, version);
});
};
sendToStorage(fileRef);
},
interceptDownload: function(http, fileRef, version) {
var path, ref, ref1, ref2;
path = (ref = fileRef.versions) != null ? (ref1 = ref[version]) != null ? (ref2 = ref1.meta) != null ? ref2.pipeFrom : void 0 : void 0 : void 0;
if (path) {
// If file is moved to DropBox
// We will pipe request to DropBox
// So, original link will stay always secure
Request({
url: path,
headers: _.pick(http.request.headers, 'range', 'accept-language', 'accept', 'cache-control', 'pragma', 'connection', 'upgrade-insecure-requests', 'user-agent')
}).pipe(http.response);
return true;
} else {
// While file is not yet uploaded to DropBox
// We will serve file from FS
return false;
}
}
});
export { Collections };
if (Meteor.isServer) {
// Intercept File's collection remove method
// to remove file from DropBox
var _origRemove = Collections.files.remove;
Collections.files.remove = function(search) {
var cursor = this.collection.find(search);
cursor.forEach(function(fileRef) {
_.each(fileRef.versions, function(vRef) {
var ref;
if (vRef != null ? (ref = vRef.meta) != null ? ref.pipePath : void 0 : void 0) {
client.remove(vRef.meta.pipePath, function(error) {
bound(function() {
if (error) {
console.error(error);
}
});
});
}
});
});
// Call original method
_origRemove.call(this, search);
};
}
if (Meteor.isServer) {
Collections.files.deny({
insert() { return true; },
update() { return true; },
remove() { return true; },
});
}
Here is the errors
/* server error */
I20160728-09:52:55.711(8)? [FilesCollection] [File Start Method] 20131124_125547.jpg - HP9HPqEgMfQWkZzSB
I20160728-09:52:55.731(8)? [FilesCollection] [Upload] [Start Method] Got #-1/7 chunks, dst: 20131124_125547.jpg
I20160728-09:52:56.225(8)? [FilesCollection] [Upload] [DDP] Got #1/7 chunks, dst: 20131124_125547.jpg
I20160728-09:52:56.376(8)? [FilesCollection] [Upload] [DDP] Got #2/7 chunks, dst: 20131124_125547.jpg
I20160728-09:52:56.436(8)? [FilesCollection] [Upload] [DDP] Got #3/7 chunks, dst: 20131124_125547.jpg
I20160728-09:52:56.515(8)? [FilesCollection] [Upload] [DDP] Got #4/7 chunks, dst: 20131124_125547.jpg
I20160728-09:52:56.546(8)? [FilesCollection] [Upload] [DDP] Got #5/7 chunks, dst: 20131124_125547.jpg
I20160728-09:52:56.561(8)? [FilesCollection] [Upload] [DDP] Got #7/7 chunks, dst: 20131124_125547.jpg
I20160728-09:52:56.625(8)? [FilesCollection] [Upload] [DDP] Got #6/7 chunks, dst: 20131124_125547.jpg
I20160728-09:52:56.638(8)? [FilesCollection] [Upload] [DDP] Got #-1/7 chunks, dst: 20131124_125547.jpg
I20160728-09:52:56.713(8)? [FilesCollection] [Upload] [finish(ing)Upload] -> assets\app\uploads\uploadedFiles\HP9HPqEgMfQWkZzSB.jpg
I20160728-09:52:56.713(8)? [FilesCollection] [Upload] [finish(ed)Upload] -> assets\app\uploads\uploadedFiles\HP9HPqEgMfQWkZzSB.jpg
I20160728-09:52:56.729(8)? [FilesCollection] [_preCollectionCursor.observeChanges] [removed]: HP9HPqEgMfQWkZzSB
I20160728-09:52:58.326(8)? [FilesCollection] [download(/cdn/storage/uploadedFiles/HP9HPqEgMfQWkZzSB/original/HP9HPqEgMfQWkZzSB.jpg, original)]
I20160728-09:52:58.333(8)? [FilesCollection] [serve(assets\app\uploads\uploadedFiles\HP9HPqEgMfQWkZzSB.jpg, original)] [200]
I20160728-09:53:03.516(8)? [FilesCollection] [Unlink Method] [.remove(HP9HPqEgMfQWkZzSB)]
I20160728-09:53:03.535(8)? [FilesCollection] [remove("HP9HPqEgMfQWkZzSB")]
I20160728-09:53:03.537(8)? [FilesCollection] [unlink(HP9HPqEgMfQWkZzSB, undefined)]
I20160728-09:53:09.453(8)? [FilesCollection] [File Start Method] 20131124_125547.jpg - CpBqKjPi8FnWEwDc7
I20160728-09:53:09.459(8)? [FilesCollection] [Upload] [Start Method] Got #-1/7 chunks, dst: 20131124_125547.jpg
I20160728-09:53:09.864(8)? [FilesCollection] [Upload] [DDP] Got #1/7 chunks, dst: 20131124_125547.jpg
I20160728-09:53:09.953(8)? [FilesCollection] [Upload] [DDP] Got #2/7 chunks, dst: 20131124_125547.jpg
I20160728-09:53:10.019(8)? [FilesCollection] [Upload] [DDP] Got #3/7 chunks, dst: 20131124_125547.jpg
I20160728-09:53:10.113(8)? [FilesCollection] [Upload] [DDP] Got #4/7 chunks, dst: 20131124_125547.jpg
I20160728-09:53:10.212(8)? [FilesCollection] [Upload] [DDP] Got #5/7 chunks, dst: 20131124_125547.jpg
I20160728-09:53:10.253(8)? [FilesCollection] [Upload] [DDP] Got #7/7 chunks, dst: 20131124_125547.jpg
I20160728-09:53:10.331(8)? [FilesCollection] [Upload] [DDP] Got #6/7 chunks, dst: 20131124_125547.jpg
I20160728-09:53:10.346(8)? [FilesCollection] [Upload] [DDP] Got #-1/7 chunks, dst: 20131124_125547.jpg
I20160728-09:53:10.378(8)? [FilesCollection] [Upload] [finish(ing)Upload] -> assets\app\uploads\uploadedFiles\CpBqKjPi8FnWEwDc7.jpg
I20160728-09:53:10.378(8)? [FilesCollection] [Upload] [finish(ed)Upload] -> assets\app\uploads\uploadedFiles\CpBqKjPi8FnWEwDc7.jpg
I20160728-09:53:10.393(8)? [FilesCollection] [_preCollectionCursor.observeChanges] [removed]: CpBqKjPi8FnWEwDc7
I20160728-09:53:12.605(8)? [FilesCollection] [download(/cdn/storage/uploadedFiles/CpBqKjPi8FnWEwDc7/original/CpBqKjPi8FnWEwDc7.jpg, original)]
I20160728-09:53:12.618(8)? [FilesCollection] [serve(assets\app\uploads\uploadedFiles\CpBqKjPi8FnWEwDc7.jpg, original)] [200]
I20160728-09:53:12.775(8)? Exception in callback of async function: TypeError: Cannot read property '_id' of undefined
I20160728-09:53:12.778(8)? at FilesCollection.exports.FilesCollection.FilesCollection.unlink (C:\projects\Testing\skillmate\.meteor\local\build\programs\server\packages\ostrio_files.js:2718:58)
I20160728-09:53:12.784(8)? at meteor://app/imports/api/images/images.js:63:22
I20160728-09:53:12.786(8)? at meteor://app/packages/mongo/collection.js:651:5
I20160728-09:53:12.789(8)? at runWithEnvironment (meteor://app/packages/meteor/dynamics_nodejs.js:110:1)
I20160728-09:53:12.792(8)? at meteor://app/packages/meteor/dynamics_nodejs.js:123:1
I20160728-09:53:12.795(8)? at meteor://app/packages/mongo/mongo_driver.js:322:7
I20160728-09:53:12.797(8)? at meteor://app/packages/mongo/mongo_driver.js:568:11
I20160728-09:53:12.804(8)? at runWithEnvironment (meteor://app/packages/meteor/dynamics_nodejs.js:110:1)
I20160728-09:53:26.966(8)? [FilesCollection] [unlink(CpBqKjPi8FnWEwDc7, original)]
I20160728-09:54:21.436(8)? [FilesCollection] [Unlink Method] [.remove(CpBqKjPi8FnWEwDc7)]
I20160728-09:54:21.443(8)? [FilesCollection] [remove("CpBqKjPi8FnWEwDc7")]
I20160728-09:54:21.454(8)? [FilesCollection] [unlink(CpBqKjPi8FnWEwDc7, undefined)]
Hi Dr.Dimitri , Thank you so much… The code works fine! Appreciated! Just a minor issue about the callback for deletion… I’ll figure it out.
I’m glad we’ve figured it out