Hello! I have an issue with uploading files via Admin UI to the FS storage.
Before updating to Keystone release version 4.0.0 the filenames were generated randomly and had extension in the end.
Now they are uploaded without an extension.
var storage = new keystone.Storage({
adapter: keystone.Storage.Adapters.FS,
fs: {
path: keystone.expandPath('./public/uploads/vendors'),
},
});
Vendor.add({
logo: {
type: Types.File,
storage: storage,
},
})
| Software | Version
| ---------------- | -------
| Keystone | 4.0.0
| Node.js | 10.8.0
| Browser | Chrome 67.0.3396.99 (64-bit)
Same issue here!
It's because a file extention is not been passed to the randomFilename function my solution was to add this line to this file.
filename = sanitize(filename) + path.parse(file.originalname).ext;
I have the same problem , any news about how to fix ??
I have the same problem , any news about how to fix ??
I did something like this to fix this:
var storage = new keystone.Storage({
adapter: keystone.Storage.Adapters.FS,
schema : {
originalname: true
},
fs: {
path: keystone.expandPath('./public/uploads/vendors'),
generateFilename: (file) => {
const ext = file.originalname.substr(file.originalname.lastIndexOf('.') + 1);
return `${file.filename}.${ext}`;
}
},
});
Same issue. But i didn't understand after what this bug started? A upload a lot of files and all files was with ext. Need research.
@Twansparant 's solution worked for me (didn't need the schema key - not sure what that does?). Another solution is to use the keystone-storage-namefunctions.originalFilename function, since that includes the extension, like so:
const keystone = require('keystone');
const keystone_namegen = require('keystone-storage-namefunctions');
const storage = new keystone.Storage({
adapter: keystone.Storage.Adapters.FS,
fs: {
path: 'uploads',
publicPath: '/public/uploads/',
generateFilename: keystone_namegen.originalFilename,
}
});
I've faced with the same issues during working with keystone-storage-s3
Mine workaround is to use mime-types as fallback for extensions
var crypto = require('crypto');
var mime = require('mime-types')
exports.randomFilename = function (file, i, callback) {
crypto.randomBytes(16, function (err, data) {
if (err) return callback(err);
return callback(null, filenameFromBuffer(data, file.extension || mime.extension(file.mimetype)));
});
};
and then reuse randomFilename as generateFilename
var keystone = require('keystone');
var _ = require( "lodash" );
var generateFileName = require('./generateFilename');
var createStorage = function(config) {
return new keystone.Storage({
adapter: require('keystone-storage-adapter-s3'),
s3: _.merge({
key: process.env.S3_KEY, // required; defaults to process.env.S3_KEY
secret: process.env.S3_SECRET, // required; defaults to process.env.S3_SECRET
bucket: process.env.S3_BUCKET, // required; defaults to process.env.S3_BUCKET
region: process.env.S3_REGION, // optional; defaults to process.env.S3_REGION, or if that's not specified, us-east-1
uploadParams: { // optional; add S3 upload params; see below for details
ACL: 'public-read',
},
generateFilename: generateFileName.randomFilename,
}, config),
schema: {
url: true
}
});
}
module.exports = createStorage;
Same issue (v4.2.1).
I've faced with the same issues during working with
keystone-storage-s3Mine workaround is to use mime-types as fallback for extensions
var crypto = require('crypto'); var mime = require('mime-types') exports.randomFilename = function (file, i, callback) { crypto.randomBytes(16, function (err, data) { if (err) return callback(err); return callback(null, filenameFromBuffer(data, file.extension || mime.extension(file.mimetype))); }); };and then reuse randomFilename as
generateFilenamevar keystone = require('keystone'); var _ = require( "lodash" ); var generateFileName = require('./generateFilename'); var createStorage = function(config) { return new keystone.Storage({ adapter: require('keystone-storage-adapter-s3'), s3: _.merge({ key: process.env.S3_KEY, // required; defaults to process.env.S3_KEY secret: process.env.S3_SECRET, // required; defaults to process.env.S3_SECRET bucket: process.env.S3_BUCKET, // required; defaults to process.env.S3_BUCKET region: process.env.S3_REGION, // optional; defaults to process.env.S3_REGION, or if that's not specified, us-east-1 uploadParams: { // optional; add S3 upload params; see below for details ACL: 'public-read', }, generateFilename: generateFileName.randomFilename, }, config), schema: { url: true } }); } module.exports = createStorage;
Hi @AlexanderMoroz !
I understand that in the first snippet of code you added || mime.extension(file.mimetype) to keystone-store-namefunctions/index.js (line 54).
In what file did you add in the second snippet of code to make it work?
Thanks for posting this!
For those of you using keystone-storage-adapter-s3 , just edit keystone-storage-namefunctions/index.js
Like @AlexanderMoroz said, put var mime = require('mime-types'); at the top and replace line 54 with return callback(null, filenameFromBuffer(data, file.extension || mime.extension(file.mimetype)));
Files are uploading with their proper extension. :)
Most helpful comment
It's because a file extention is not been passed to the randomFilename function my solution was to add this line to this file.
filename = sanitize(filename) + path.parse(file.originalname).ext;https://github.com/keystonejs/keystone/blob/20a7723b6a3682f1c4e87750e832de564d83a590/lib/storage/adapters/fs/index.js#L97