Hello,
First of all thanks for feather.js, it's amazing and fits all the requirements for my project. 馃檹
So I have a simple API and I followed this tutorial to create a /upload service, which works pretty nice.
const service = require('feathers-mongoose');
const upload = require('./upload-model');
const hooks = require('./hooks');
const multer = require('multer');
const multipartMiddleware = multer();
const appRoot = require('app-root-path');
const path = require('path');
const fs = require('fs-blob-store');
const blobService = require('feathers-blob');
const blobStorage = fs(`${appRoot}/uploads`);
module.exports = function() {
const app = this;
const options = {
Model: upload
};
// Initialize our service with any options it requires
app.use('/uploads',
// multer parse the file
// data stored in memory
multipartMiddleware.single('uri'),
// midleware
// transfer the file to feathers
(req, res, next) => {
req.feathers.file = req.file;
next();
},
blobService({Model: blobStorage})
);
// Get our initialize service to that we can bind hooks
const uploadService = app.service('/uploads');
// Set up our before hooks
uploadService.before(hooks.before);
// Set up our after hooks
uploadService.after(hooks.after);
};
And the hooks:
const uploadHook = require('./uploadHook');
const globalHooks = require('../../../hooks');
const hooks = require('feathers-hooks');
const auth = require('feathers-authentication').hooks;
exports.before = {
all: [
//auth.verifyToken(),
//auth.populateUser(),
//auth.restrictToAuthenticated()
],
find: [],
get: [],
create: [
uploadHook()
],
update: [
hooks.disable()
],
patch: [
hooks.disable()
],
remove: []
};
exports.after = {
all: [],
find: [],
get: [],
create: [],
update: [],
patch: [],
remove: []
};
The only thing I want to do is to save the path of my uploaded file in the database.
I was thinking to create a new service for handling saving in the database, so after I recive the response from the server to call my saveToDB service and pass the filepath, but dosent feel right.
Its there a better way to combine upload and feathers-mongoose service?
If you already have a service that is mapped to the DB resource that you want to store the location on you can just call a patch or create on it, in an after hook after the upload is complete.
Take the example of a profile photo. You probably want to store that on the user, and you probably already have a User service. So you can simple call hook.app.service('users').patch(hook.user._id, { avatar: filepath }).then(...).
Hey @ekryski, thanks for you answer!
I'm actually building a chat app with react-native.
The thing is that I want to save as you said, so I'm saving the image as a message with an after hook like:
const createAfter = function(hook) {
return function(hook) {
const messages = hook.app.service('messages');
const { topic, filePath } = hook.data;
messages.create({ filePath, topic })
.then((result) => {
Object.assign(hook.result, result);
// merge hook.result with result
// this is not working, probably because of the promise
// on client I still get hook.result without result object
})
.catch((error) => {
new Error(error);
});
}
}
However on the client in the console.log I recive the hook.result without the messages result (filePath and topic keys are missing from the result object).
How can I manage something like this with Feathers? I'm doing something wrong?
Thanks! 馃憦
Anyone? 馃挴
@indie314 if you modify the results on the server and are using mongoose you need to call toObject on it first or put the bundled hook we provide in your hook chain. You can alternatively you can use Object.assign but you need to create a new object, not modify the original.
Object.assign({}, hook.result, result)
Hopefully that helps ya!
Closing. Please feel free to reopen with more information if the last reply didn't solve the problem.
Is this a compliant to REST design though? Putting all uploads into a single /uploads.
If I want to upload a profile picture, I should PATCH /users/id with the picture. If I want to add a photo of let's say a car, I should then POST /cars with the photo in the body.
With this method, all uploads are going through /uploads, and I guess there will be some logic in the UploadService which looks at some meta-fields in the body, and patches the corresponding UserService/CarService.
Is there a way to use feathers-blob without creating an additional /uploads route?
@amaurymartiny i'm not sure POST /cars it's user cars ?
so POST /user/id/pictures/cars with your logic
GET user picture it's the path to picture
POST or PATCH picture it's the application upload pictures service , not users service
POST /upload/:user_id/avatar/default.png
POST /upload/:user_id/:album_id/car.png
if you custom your service upload
look Facebook strategy. or upload : file system VS db persist
@amaurymartiny and anyone else tearing their hair out:
app.use('/tasks',
// multer parses the file named 'uri'.
// Without extra params the data is
// temporarely kept in memory
multipartMiddleware.single('uri'),
// another middleware, this time to
// transfer the received file to feathers
function(req,res,next){
req.feathers.file = req.file;
next();
},
service);
will put the file into params.file (i'm using feathers-mongoose) in your tasks service method method handler (e.g. put <=> update)
This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue with a link to this issue for related bugs.
Most helpful comment
Is this a compliant to REST design though? Putting all uploads into a single
/uploads.If I want to upload a profile picture, I should
PATCH /users/idwith the picture. If I want to add a photo of let's say a car, I should thenPOST /carswith the photo in the body.With this method, all uploads are going through
/uploads, and I guess there will be some logic in the UploadService which looks at some meta-fields in the body, and patches the corresponding UserService/CarService.Is there a way to use
feathers-blobwithout creating an additional/uploadsroute?