Skip to content

Buffer upload in assets #303

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Mar 26, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

## [v1.19.6](https://github.com/contentstack/contentstack-management-javascript/tree/v1.19.6) (2025-03-31)
- Enhancement
- Added buffer upload in assets

## [v1.19.5](https://github.com/contentstack/contentstack-management-javascript/tree/v1.19.5) (2025-03-17)
- Fix
- Added AuditLog in the stack class
Expand Down
18 changes: 14 additions & 4 deletions lib/stack/asset/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -291,11 +291,21 @@ export function createFormData (data) {
if (typeof data.title === 'string') {
formData.append('asset[title]', data.title)
}
const uploadStream = createReadStream(data.upload)
if (typeof data.content_type === 'string') {
formData.append('asset[upload]', uploadStream, { contentType: data.content_type })
// Handle Buffer Upload
if (Buffer.isBuffer(data.upload)) {
formData.append('asset[upload]', data.upload, {
filename: data.filename || 'uploaded_file',
contentType: data.content_type || 'application/octet-stream'
})
} else if (typeof data.upload === 'string') { // Handle File Path Upload
const uploadStream = createReadStream(data.upload)
if (typeof data.content_type === 'string') {
formData.append('asset[upload]', uploadStream, { contentType: data.content_type })
} else {
formData.append('asset[upload]', uploadStream)
}
} else {
formData.append('asset[upload]', uploadStream)
throw new Error('Invalid upload format. Must be a file path or Buffer.')
}
return formData
}
Expand Down
6 changes: 4 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
"author": "Contentstack",
"license": "MIT",
"dependencies": {
"axios": "^1.8.2",
"axios": "^1.8.3",
"form-data": "^4.0.2",
"lodash": "^4.17.21",
"qs": "^6.14.0"
Expand Down
26 changes: 26 additions & 0 deletions test/sanity-check/api/asset-test.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import fs from 'fs'
import path from 'path'
import { expect } from 'chai'
import { describe, it, setup } from 'mocha'
Expand Down Expand Up @@ -39,6 +40,31 @@ describe('Assets api Test', () => {
.catch(done)
})

it('should upload asset from buffer', (done) => {
const filePath = path.join(__dirname, '../mock/customUpload.html')
const fileBuffer = fs.readFileSync(filePath) // Read file into Buffer
const asset = {
upload: fileBuffer, // Buffer upload
filename: 'customUpload.html', // Ensure filename is provided
content_type: 'text/html', // Set content type
title: 'buffer-asset',
description: 'Buffer Asset Desc',
tags: ['Buffer']
}
makeAsset().create(asset)
.then((asset) => {
jsonWrite(asset, 'bufferAsset.json')
expect(asset.uid).to.be.not.equal(null)
expect(asset.url).to.be.not.equal(null)
expect(asset.filename).to.be.equal('customUpload.html')
expect(asset.title).to.be.equal('buffer-asset')
expect(asset.description).to.be.equal('Buffer Asset Desc')
expect(asset.content_type).to.be.equal('text/html')
done()
})
.catch(done)
})

it('should download asset from URL.', done => {
makeAsset().download({ url: assetURL, responseType: 'stream' })
.then((response) => {
Expand Down
44 changes: 44 additions & 0 deletions test/unit/asset-test.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import fs from 'fs'
import path from 'path'
import Axios from 'axios'
import { expect } from 'chai'
Expand Down Expand Up @@ -171,6 +172,49 @@ describe('Contentstack Asset test', () => {
.catch(done)
})

it('should upload asset from buffer', (done) => {
const mock = new MockAdapter(Axios)
mock.onPost('/assets').reply(200, {
asset: {
uid: 'mock-uid',
url: '/assets',
filename: 'customUpload.html',
title: 'buffer-asset',
description: 'Buffer Asset Desc',
content_type: 'text/html',
tags: ['Buffer'],
parent_uid: 'UID'
}
})
const filePath = path.join(__dirname, '../api/mock/customUpload.html')
const fileBuffer = fs.readFileSync(filePath)
const assetUpload = {
upload: fileBuffer, // Buffer upload
filename: 'customUpload.html', // Filename to identify the file
content_type: 'text/html', // MIME type
title: 'buffer-asset',
description: 'Buffer Asset Desc',
tags: ['Buffer'],
parent_uid: 'UID'
}
const form = createFormData(assetUpload)() // Create FormData for Buffer upload
const boundary = form.getBoundary()
expect(boundary).to.be.equal(form.getBoundary())
expect(boundary.length).to.be.greaterThan(30)
makeAsset()
.create(assetUpload)
.then((asset) => {
expect(asset.uid).to.be.equal('mock-uid')
expect(asset.filename).to.be.equal('customUpload.html')
expect(asset.title).to.be.equal('buffer-asset')
expect(asset.description).to.be.equal('Buffer Asset Desc')
expect(asset.content_type).to.be.equal('text/html')
expect(asset.tags).to.include('Buffer')
done()
})
.catch(done)
})

it('Asset replace test', done => {
var mock = new MockAdapter(Axios)
mock.onPut('/assets/UID').reply(200, {
Expand Down
Loading