Reputation: 1
Well im working on a music distrubute panel for a customer, the music upload file won't work and gives error.
Audio upload error: TypeError: Cannot read properties of undefined (reading 'pipe')
at C:\Users\nmson\Desktop\xxlclan\node_modules\node-appwrite\lib\services\storage.js:455:25
at new Promise (<anonymous>)
at Storage.createFile (C:\Users\nmson\Desktop\xxlclan\node_modules\node-appwrite\lib\services\storage.js:393:22)
at file:///C:/Users/nmson/Desktop/xxlclan/server/router/upload-music.js:195:23
at Layer.handle [as handle_request] (C:\Users\nmson\Desktop\xxlclan\node_modules\express\lib\router\layer.js:95:5)
at next (C:\Users\nmson\Desktop\xxlclan\node_modules\express\lib\router\route.js:149:13)
at done (C:\Users\nmson\Desktop\xxlclan\node_modules\multer\lib\make-middleware.js:45:7)
at indicateDone (C:\Users\nmson\Desktop\xxlclan\node_modules\multer\lib\make-middleware.js:49:68)
at Multipart.<anonymous> (C:\Users\nmson\Desktop\xxlclan\node_modules\multer\lib\make-middleware.js:166:7)
at Multipart.emit (node:events:524:28)
and I don't know what to do.
the full code of uploadmusic.js
import express from 'express';
import multer from 'multer';
import { Client, Storage, Databases, ID, InputFile } from 'node-appwrite';
import path from 'path';
import dotenv from 'dotenv';
import { Readable } from 'stream';
dotenv.config();
const router = express.Router();
const DB_ID = process.env.DATABASE_ID;
const COLLECTION_ID = process.env.COLLECTION_ID;
const BUCKET_ID = '';
const client = new Client()
.setEndpoint(process.env.APPWRITE_ENDPOINT)
.setProject(process.env.APPWRITE_PROJECT_ID)
.setKey(process.env.APPWRITE_API_KEY);
const storage = new Storage(client);
const databases = new Databases(client);
const upload = multer({
storage: multer.memoryStorage(),
limits: {
fileSize: 50 * 1024 * 1024, // 50MB limit
},
fileFilter: (req, file, cb) => {
const allowedAudioTypes = ['audio/wav', 'audio/x-wav', 'audio/wave', 'audio/mpeg', 'audio/mp3'];
const allowedImageTypes = ['image/jpeg', 'image/png'];
if (file.fieldname === 'audioFile' && allowedAudioTypes.includes(file.mimetype)) {
cb(null, true);
} else if (file.fieldname === 'artworkFile' && allowedImageTypes.includes(file.mimetype)) {
cb(null, true);
} else {
cb(new Error('Invalid file type'));
}
}
});
router.post('/upload', upload.fields([
{ name: 'audioFile', maxCount: 1 },
{ name: 'artworkFile', maxCount: 1 }
]), async (req, res) => {
res.setHeader('Content-Type', 'application/json');
try {
// Validate files exist
if (!req.files?.audioFile?.[0] || !req.files?.artworkFile?.[0]) {
return res.status(400).json({
success: false,
message: 'Both audio and artwork files are required'
});
}
console.log('Processing upload:', {
timestamp: new Date().toISOString(),
files: {
audio: req.files.audioFile[0].originalname,
artwork: req.files.artworkFile[0].originalname
}
});
const audioFile = req.files.audioFile[0];
const artworkFile = req.files.artworkFile[0];
const audioId = ID.unique();
const artworkId = ID.unique();
try {
await Promise.all([
storage.createFile(BUCKET_ID, audioId, audioFile.buffer, {
contentType: audioFile.mimetype,
filename: audioFile.originalname
}),
storage.createFile(BUCKET_ID, artworkId, artworkFile.buffer, {
contentType: artworkFile.mimetype,
filename: artworkFile.originalname
})
]);
} catch (fileError) {
console.error('File upload error:', fileError);
return res.status(500).json({
success: false,
message: 'Failed to upload files',
error: fileError.message
});
}
// Create database entry
const documentId = ID.unique();
const document = await databases.createDocument(
DB_ID,
COLLECTION_ID,
documentId,
{
// Required fields
releaseTitle: req.body.releaseTitle,
artistName: req.body.artistName,
lyricsLanguage: req.body.lyricsLanguage,
composerName: req.body.composerName,
lyricistName: req.body.lyricistName,
explicitContent: req.body.explicitContent === 'yes',
label: req.body.label,
genre: req.body.genre,
releaseDate: req.body.releaseDate,
// Optional fields
spotifyArtistLink: req.body.spotifyArtistLink || null,
appleMusicArtistLink: req.body.appleMusicArtistLink || null,
featuredArtist: req.body.featuredArtist || null,
spotifyFeaturedLink: req.body.spotifyFeaturedLink || null,
appleMusicFeaturedLink: req.body.appleMusicFeaturedLink || null,
upc: req.body.upc || null,
isrc: req.body.isrc || null,
previewStartTime: req.body.previewStartTime ? parseInt(req.body.previewStartTime) : 0,
additionalNotes: req.body.additionalNotes || null,
// File IDs
audioFileId: audioId,
artworkFileId: artworkId,
// System fields
status: 'pending',
uploadDate: new Date().toISOString(),
lastModified: new Date().toISOString(),
isPublished: false,
// Analytics fields
streams: 0,
revenue: 0,
likes: 0,
shares: 0,
// Metadata
audioFileName: audioFile.originalname,
audioFileSize: audioFile.size,
audioMimeType: audioFile.mimetype,
artworkFileName: artworkFile.originalname,
artworkFileSize: artworkFile.size,
artworkMimeType: artworkFile.mimetype
}
);
return res.status(200).json({
success: true,
message: 'Upload successful',
documentId: document.$id,
files: {
audio: audioId,
artwork: artworkId
}
});
} catch (error) {
console.error('Upload Error:', error);
return res.status(500).json({
success: false,
message: error.message || 'Upload failed',
error: process.env.NODE_ENV === 'development' ? error.stack : undefined
});
}
});
router.post('/audio', upload.single('audioFile'), async (req, res) => {
res.setHeader('Content-Type', 'application/json');
try {
if (!req.file) {
return res.status(400).json({
success: false,
message: 'No audio file provided'
});
}
const audioFile = req.file;
const audioFileId = ID.unique();
// Convert Buffer to Readable Stream
const audioStream = Readable.from(audioFile.buffer);
await storage.createFile(
BUCKET_ID,
audioFileId,
audioStream, // Pass the stream instead of buffer
{
contentType: audioFile.mimetype,
filename: audioFile.originalname,
permissions: ['role:all']
}
);
return res.status(200).json({
success: true,
message: 'Audio file uploaded successfully',
audioFileId: audioFileId,
fileName: audioFile.originalname,
fileSize: audioFile.size,
mimeType: audioFile.mimetype
});
} catch (error) {
console.error('Audio upload error:', error);
return res.status(500).json({
success: false,
message: error.message || 'Failed to upload audio file'
});
}
});
export default router;
I couldn't do anything because I didn't knew what it'd cause the code more. the code first checks if it's the correct audio file, then uploads to the bucket id, saves the entered informations to the db and yea..
Upvotes: 0
Views: 23
Reputation: 712
await storage.createFile(
BUCKET_ID,
audioFileId,
audioStream, // Pass the stream instead of buffer
{
contentType: audioFile.mimetype,
filename: audioFile.originalname,
permissions: ['role:all']
}
);
This doesn't quite look right, especially with the latest version of the SDK (15.0.0). The function signature is:
async createFile(bucketId: string, fileId: string, file: File, permissions?: string[], onProgress = (progress: UploadProgress) => {}): Promise<Models.File>
So the 4th argument should be an array, not an object.
As for the 3rd argument, it should be a File
object. There are some helpers for this in node-appwrite/file
.
import { InputFile } from 'node-appwrite/file';
InputFile.fromBuffer(parts: Blob | BinaryLike, name: string);
InputFile.fromPath(path: string, name: string);
InputFile.fromPlainText(content: string, name: string);
Since you have audioFile.buffer
, I would expect you to use:
InputFile.fromBuffer(audioFile.buffer, audioFile.originalname);
Reference:
Upvotes: 0