[Meta issue] Upload plugin
Link to the documentation page or resource
https://docs.strapi.io/dev-docs/plugins/upload
Describe the bug
Hi, I'm Pierre, Lead Technical Writer at Strapi.
We noticed users have reported several errors or outdated instructions about the Upload plugin.
I will group these issues here on a single "meta" page. We are currently heavily focused on documenting v5, the upcoming v4 features, and Strapi Cloud, but updating the Upload plugin documentation is in our backlog (and the page will most probably be updated during v5 development to match the new data formats).
Issues reported by users:
- [ ] #1855
- [ ] #1379
- [ ] #926
In the meantime, if would like to create a documentation PR to update the Upload documentation and fix any of the aforementioned issues, we'd be super happy to review it 🤗
Hi, I'm not sure if this is the correct spot to report this, but the documentation of the S3 Upload Plugin is out of date.
The doc described here, https://docs.strapi.io/dev-docs/plugins/upload, links to this S3 plugin page, but I'm not sure where to post this as an issue since the strapi monorepo points to this documentation repo for doc updates.
Long story short, the S3 plugin page's Configuration erroneously points to AWS SDK v2 docs, not the new v3 documentation. This led to a lot of frustration for my team as we tried to configure the plugin to work with our company's forward proxy.
Here are the v3 AWS SDK Docs for S3: https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/s3/#s3clientconfig
Hi @d717an. I'm sorry you're having troubles with the S3 Upload plugin. Could you please create an issue in the strapi/strapi repo? As this is where the documentation for this package is managed, and I don't have control over this repo. https://github.com/strapi/strapi/tree/main/packages/providers/upload-aws-s3
If you don't get any reply, I'll ping some engineers so they can have a quicker look to it.
Thanks @pwizla, created.
No time pressure from my end on this; our issue is solved now that we know where to look. This improvement will be for other strapi users.
Hey team,
If nobody has picked this up I'd love to make my first contribution! I have been dwelling on supporting open source, and I feel starting by contributing via documentation would be good. Let me know! @pwizla
Thanks, @d717an! If no engineer takes care of your issue feel free to ping me and I'll create a PR myself in this other repo so it does not get stuck for too long (and I'll try to push them for a quick review 😄 🏃)
Hi @SpeedAD and thank you for your enthusiasm and willingness to help! I am not sure what you would like to work on, though 🤔 What did you have in mind? 🙂
(Edit: if you were looking for an easy, first time contribution, you can create a pull request to fix the following issue: https://github.com/strapi/documentation/issues/2056 )
@pwizla Well I landed here after i saw #20003 on the main strapi/strapi repository. So i thought I can help by rectifying the link on the documentation
(Edit: Thanks for mentioning the easy one for me :) Planning to fork the documentation repo now)
Oh, I see @SpeedAD! So you can probably create a PR for #20003 on the strapi/strapi repo. I won't review it because I only maintain the strapi/documentation repository, but if in the future you need any help about creating PRs for strapi/documentation please just let me know 😊
Not sure if this is the right place for feedback, but I'm trying to understand the documentation of the upload plugin and adapt it to flutter, but it's very confusing, particularly the javascript code snippets. It feels like whoever wrote it is trying to show off his javascript skills more than actually making the code clear. I would suggest a better javascript code snippet, but I'm still trying to understand what it does.
https://docs.strapi.io/dev-docs/plugins/upload#upload-files-at-entry-creation
I just want to have my files uploaded together with the entry, a simple expected json body would be a more universal way of showing what strapi expects. A less javascripty code snippet would be much appreciated too, since strapi is used with other languages.
Thanks.
I spent a lot of time getting this to work and had similar problems with the documentation.
I'll do my best to document how I did it and it may be less javascripty but will be way more typescripty. Some of the code is specific to my types defined in my cms and you'll need to adjust for yours .
To start, I have the following types defined:
TYPES
I massage the data coming from the CMS into these types, but they're pretty close.
export type TImageMeta = { file: File; fileData: string };
export type TCmsAsset = {
id: number;
alternativeText: string;
caption: string;
baseCmsAssetMeta: TCmsAssetMeta;
cmsAssetMetaFormats: {
thumbnail: TCmsAssetMeta;
small: TCmsAssetMeta;
medium: TCmsAssetMeta;
large: TCmsAssetMeta;
};
};
export type TCmsAssetMeta = {
ext: string;
hash: string;
height: number;
mime: string;
name: string;
provider: string;
size: number;
url: string;
width: number;
};
** HELPER METHODS **
export const prepareStrapiFilePost = (
files: Array<TImageMeta>,
cmsAssetName?: string, // this is the name of the class/object in the cms e.g. `properties`, used for create not update
filenamePrefix?: string, //optional
): FormData => {
const resultForm = new FormData()
files.forEach((f: TImageMeta) => {
const isBase64Str: boolean = f.fileData.indexOf(';base64,') !== -1
if (isBase64Str) {
const base64String = f.fileData.split(';base64,').pop()
if (base64String?.length) {
const fileBuffer = Buffer.from(base64String, 'base64')
const arraybuffer = new Blob([fileBuffer], { type: f.file.type })
resultForm.append(
`files${cmsAssetName ? `.${cmsAssetName}` : ''}`,
arraybuffer,
`${!filenamePrefix ? '' : `${filenamePrefix}-`}${uuidv4().replace(/-/g, '')}`,
)
}
} else {
throw new Error('Only base64 image data is supported')
}
})
return resultForm
}
export const strapiPostData = async (options: StrapiFetchOptions): Promise<void> => {
try {
const url = `${strapiUrl}${options.url}`
logger.info('strapiPostData: url', { message: url })
const response = await fetch(url, {
method: 'post',
headers: {
Authorization: `Bearer ${AppConfig.strapiApiKey}`,
...options.headers,
},
body: options.body,
})
if (!response.ok) {
await logStrapiResponseError(response)
const errResp = `CMS returned ${response.status} for ${url}`
logger.error(errResp)
throw new Error(errResp)
}
// const serializedJson = await response.json()
// logger.info('serializedJson', {serializedJson})
} catch (err: any) {
logger.error('strapiPostData: failed with message', { message: err })
throw err
}
return
}
CREATE AND UPDATE*
When I get the files from the client I do the following:
// prepare CMS Assets for update. formJson is data posted from the client
const isCmsCreate = !formJson.assetId || formJson.assetId.length === 0
const currAssetId = !isCmsCreate ? formJson.assetId : uuidv4()
let cmsFormData: FormData
if (!isCmsCreate) {
cmsFormData = prepareStrapiFilePost(formJson.files, undefined, userId.replace(/-/g, ''))
cmsFormData.append('ref', 'api::pool-asset.pool-asset')
cmsFormData.append('refId', `${formJson.cmsPoolAssetId}`)
cmsFormData.append('field', 'assets')
} else {
const data: any = {}
cmsFormData = prepareStrapiFilePost(formJson.files, 'assets', userId.replace(/-/g, ''))
data['poolId'] = poolId
data['assetId'] = currAssetId
cmsFormData.append('data', JSON.stringify(data))
}
// push assets to CMS
if (formJson.files.length) {
if (isCmsCreate) {
await strapiPostData({
url: '/pool-assets',
body: cmsFormData,
method: 'post',
})
} else {
// UPDATE EXISTING FILES INSIDE A ASSET.
await strapiPostData({
url: '/upload',
body: cmsFormData,
method: 'post',
})
}
Hope this helps.