Closed yeung108 closed 4 years ago
@yeung108 This feature is in progress. I will provide an update as soon as it is ready
I try do it too :), @nazirov91 have some alternate to make uploads?
Yes, I am currently testing it. I will update the repo soon
I use 64encode and save i text field in strapi
@yeung108 @devalexandre Hi guys,
I have added the file upload feature to the data provider. Could you please try it on your projects and let me know if it works correctly? Instructions are given in the Readme file on the main page of this repo.
Thank you!
@nazirov91: Thank you for the effort to do this adapter ! It really looks good. I'm having some troubles trying to upload an image and I thought you might want to know.
I followed your instructions but I got this error:
[2020-03-22T16:02:04.873Z] error TypeError: Cannot read property 'toString' of undefined at /../backend/node_modules/strapi-connector-mongoose/lib/relations.js:288:24 at Array.map (<anonymous>) at /../backend/node_modules/strapi-connector-mongoose/lib/relations.js:287:68 at Array.reduce (<anonymous>) at Function.update [as updateRelations] (/../backend/node_modules/strapi-connector-mongoose/lib/relations.js:38:59) at runMicrotasks (<anonymous>) at processTicksAndRejections (internal/process/task_queues.js:85:5) at async Object.update (/../backend/node_modules/strapi/lib/services/entity-service.js:91:17) at async Object.update (/../backend/node_modules/strapi/lib/core-api/controller.js:125:18) at async /../backend/node_modules/strapi/lib/middlewares/router/utils/routerChecker.js:77:22 at async module.exports (/../backend/node_modules/strapi-plugin-users-permissions/config/policies/isAuthenticated.js:6:3) at async Object.module.exports [as isauthenticated] (/../backend/node_modules/strapi-plugin-users-permissions/config/policies/isAuthenticated.js:6:3) at async module.exports (/../backend/node_modules/strapi-plugin-users-permissions/config/policies/permissions.js:106:12) at async /../backend/node_modules/strapi-utils/lib/policy.js:52:5
My component looks like:
<ImageInput source="image" label="New Image" accept="image/*">
<ImageField source="url" title="Record image" />
</ImageInput>
The records.setting.json
"image": {
"model": "file",
"via": "related",
"plugin": "upload",
"required": false
}
In the App.js
const uploadFields = ["image"];
const dataProvider = strapiProvider('http://localhost:1337', httpClient, uploadFields);
What am I missing ?
Hi @ismatim,
I was able to reproduce the issue you are having. And after doing some research I realized that the issue is probably related to a bug instrapi-connecter-mongoose
, not react-admin. Maybe this one https://github.com/strapi/strapi/issues/4918? I am not sure.
But I have tested this upload feature with SqlLite3, MySql and Postgres, and those are working fine.
Unfortunately, I have to assume that the upload feature for this data provider won't work until somebody fixes the bug in the mongoose connector.
If you do find a workaround for this, please let me know.
Thanks! Sardor
Hey @nazirov91 thanks for taking the time!
I kept checking and I found that the issue might come from the strapi.entityService.uploadFile
I override the create
function in the controller and the services:
create: async ctx => {
let entity;
if (ctx.is('multipart')) {
const { data, files } = parseMultipartData(ctx);
entity = await strapi.services.records.create(data, { files });
} else {
entity = await strapi.services.records.create(ctx.request.body);
}
return sanitizeEntity(entity, { model: strapi.models.records });
}
The controller works fine but, in the service:
async create(data, { files } = {}) {
console.log('service:create');
console.log('data:');
console.log(data)
delete data.image // I got to delete this to create the entity
const entry = await strapi.query('records').create(data);
console.log(files);
if (files) {
// automatically uploads the files based on the entry and the model
await strapi.entityService.uploadFiles(entry, files, {
model: strapi.models.records,
}); //but, still got an exception here!
return this.findOne({ id: entry.id });
}
return entry;
}
I didn't get along enough with strapi.entityService
to know what's happening buy you might be right it has something to do with mongoose-connector !
Are you able to upload images through Postman?
Yes, it works to the endpoint /upload
.
I think I found a solution. Can you try the following change and see if it works?
Inside the index.js
(aka ra-strapi-rest.js), there is function called handleFileUpload
. Inside the for loop, there is this piece
data[fieldName] = [...newFilesToAdd, ...existingFiles];
So comment this line out, and add this piece instead
const existingFileIds = [];
for (let ef of existingFiles) {
existingFileIds.push(ef._id);
}
data[fieldName] = [...existingFileIds];
Your handleFileUpload
function should look like this:
const handleFileUpload = (type, resource, params, uploadFieldNames) => {
const {
created_at,
updated_at,
createdAt,
updatedAt,
...data
} = params.data;
const id = type === UPDATE ? `/${params.id}` : "";
const url = `${apiUrl}/${resource}${id}`;
const requestMethod = type === UPDATE ? "PUT" : "POST";
const formData = new FormData();
const newFilesToAdd = [];
for (let fieldName of uploadFieldNames) {
let fieldData = params.data[fieldName];
fieldData = !Array.isArray(fieldData) ? [fieldData] : fieldData;
let newFiles = fieldData.filter(f => f.rawFile instanceof File);
let existingFiles = fieldData.filter(f => !(f.rawFile instanceof File));
for (let newFile of newFiles) {
newFilesToAdd.push({
src: newFile.rawFile,
title: params.data.title
});
formData.append(`files.${fieldName}`, newFile.rawFile);
}
//data[fieldName] = [...newFilesToAdd, ...existingFiles];
const existingFileIds = [];
for (let ef of existingFiles) {
existingFileIds.push(ef._id);
}
data[fieldName] = [...existingFileIds];
}
formData.append("data", JSON.stringify(data));
return httpClient(url, {
method: requestMethod,
body: formData
}).then(response => ({ data: response.json }));
};
Also revert back all the overrides you did in Strapi controllers
Yes, it works perfectly !
Without the revert I did receive the message of error about attributes
but, anyway, It's already working perfectly ! 👏 👏 👏
Are you going to add the change ?
Thank you !
Sweet! Yes, I will add this change. I just have to find a clean way to identify the db type and run different logics for file IDs
Thank you for discovering this issue and reporting!
Sweet! Yes, I will add this change. I just have to find a clean way to identify the db type and run different logics for file IDs
I think, the simplest way is to added to the constructor, I doubt there is a way to get that from strapi api.
Do you know if the property _id
is not needed for other DBs ? I don't think that might affect others connectors.
What I read and understood so far is that Strapi has better support for mongoose than other dbs.
Ping me back if you need any help.
I actually found an even better way to handle SQL and NoSQL DBs. Take a look at the latest index.js file if you are interested 😃
Turns out we do not need to know the DB type. We just need to provide the IDs of the existing files during (only) UPDATE
. And that can be done by simply adding this logic item.id || item._id
.
Exactly, that's what I thought. I've already downloaded.
BTW, did you try the multiple delete from react-admin list ? Check on each row and then delete them ? I couldn't but, individually it works. Should I create an issue for that ?
What kind of error are you getting? I just tested it with MongoDB and it worked fine. I had 5 items on the list, I randomly selected 2 of them, and deleted. Both items were deleted successfully. If it is not too much trouble for you, please go ahead and create an issue. We will figure it out
What kind of error are you getting? I just tested it with MongoDB and it worked fine. I had 5 items on the list, I randomly selected 2 of them, and deleted. Both items were deleted successfully. If it is not too much trouble for you, please go ahead and create an issue. We will figure it out
Yes, you're right. :)
File upload functionality is working fine with all available databases. Closing this issue. Thanks!
Hi is is possible to handle file uploading to Strapi for some records in the future? I have tried using FormData and FileInput from react-admin but was not able to produce successful result. Thanks