Upload API with NextJS and Azure Portal not working?
Hello, I always get an error message when I upload videos via the API in the Azure Portal. Sometimes it looks like this:
Parsed files: { videoFile: [ PersistentFile { _events: [Object: null prototype], _eventsCount: 1, _maxListeners: undefined, lastModifiedDate: 2024-12-17T10:12:37.964Z, filepath: 'C:\\Users\\thoma\\AppData\\Local\\Temp\\19612948a7cd7d81f78632e00.mp4', newFilename: '19612948a7cd7d81f78632e00.mp4', originalFilename: 'sample-2.mp4', mimetype: 'video/mp4', hashAlgorithm: false, size: 30424618, _writeStream: [WriteStream], hash: null, [Symbol(shapeMode)]: false, [Symbol(kCapture)]: false } ] }
Sometimes (it seems to often work with smaller files) and the log looks like this:
Uploading file from path: C:\Users\thoma\AppData\Local\Temp\19612948a7cd7d81f78632e00.mp4 Request timed out! File uploaded to Azure successfully: sample-2.mp4
Here I upload the API code:
import { BlobServiceClient, generateBlobSASQueryParameters, BlobSASPermissions } from '@azure/storage-blob'; import formidable from 'formidable'; import fs from 'fs/promises'; import { v4 as uuidv4 } from 'uuid'; export const config = { api: { bodyParser: false, // Disable default body parsing for file uploads }, }; // Azure Storage connection string const AZURE_STORAGE_CONNECTION_STRING = 'DefaultEndpointsProtocol=https;AccountName=innowesovideos;AccountKey=uyJz3dlCW/hd+t3Y48pSfuk1Q+pV63S1Hs48uvGIJW3ubaO/ngtSMrzoKRvBE4so7MP9zz73uaLl+AStwmS6EA==;EndpointSuffix=core.windows.net'; export default async function handler(req, res) { if (req.method !== 'POST') { return res.status(405).json({ message: 'Only POST requests are allowed' }); } let filePath = ''; // Variable to track the file path for cleanup try { // Set a timeout to prevent stalls const timeout = setTimeout(() => { console.error('Request timed out!'); if (!res.writableEnded) { res.status(504).json({ message: 'Request timed out. Please try again.' }); } }, 15000); // 15-second timeout // Initialize formidable for file parsing const form = formidable({ keepExtensions: true, // Keep file extensions maxFileSize: 5000 * 1024 * 1024, }); console.log('New filesize') // Parse the incoming form data const { files } = await new Promise((resolve, reject) => { form.parse(req, (err, fields, files) => { if (err) { console.error('Error parsing form:', err); reject(err); } else { resolve({ fields, files }); } }); }); console.log('Parsed files:', files); // Normalize videoFile input (handle single and multiple files) const fileData = Array.isArray(files.videoFile) ? files.videoFile[0] : files.videoFile; // Validate file presence and format if (!fileData || !fileData.filepath) { throw new Error('No video file provided.'); } filePath = fileData.filepath; if (!filePath) throw new Error('No valid file path found.'); if (fileData.mimetype !== 'video/mp4') throw new Error('Only MP4 files are allowed.'); console.log('Uploading file from path:', filePath); // Generate a unique file name for Azure Blob Storage const fileName = fileData.originalFilename || `${uuidv4()}.mp4`; // Load the file as a buffer const fileBuffer = await fs.readFile(filePath); // Initialize Azure Blob Storage Client const blobServiceClient = BlobServiceClient.fromConnectionString(AZURE_STORAGE_CONNECTION_STRING); const containerClient = blobServiceClient.getContainerClient('videos'); const blockBlobClient = containerClient.getBlockBlobClient(fileName); // Upload the file to Azure Blob Storage await blockBlobClient.uploadData(fileBuffer, { blobHTTPHeaders: { blobContentType: 'video/mp4' }, }); // Generate a SAS token for the uploaded file const sasToken = generateBlobSASQueryParameters( { containerName: 'videos', blobName: fileName, permissions: BlobSASPermissions.parse('r'), // Read permissions startsOn: new Date(), expiresOn: new Date(new Date().valueOf() + 3600 * 1000), // Token valid for 1 hour }, blobServiceClient.credential ).toString(); const videoUrl = `${blockBlobClient.url}?${sasToken}`; clearTimeout(timeout); return res.status(200).json({ message: 'Video uploaded successfully', videoUrl }); } catch (error) { console.error('Error during upload:', error.message); return res.status(500).json({ message: 'File upload failed', error: error.message }); } finally { if (filePath) { try { await fs.unlink(filePath); console.log(`Temporary file deleted: ${filePath}`); } catch (cleanupErr) { console.error(`Failed to delete temporary file: ${filePath}`, cleanupErr); } } } }
Thanks!
I cannot read out any real error behavior from your information yet.
This issue:
comes from your console output here:
and the timeout is explicitly covered by your script.
With larger files it is not surprising. Maybe you just set the timeout higher. For example, at 2-5 minutes instead of only 15 seconds.
However, I do not see any indication that the upload had failed. expenditure
indicate a successful upload.
Can I somehow query the upload state to see how much percent of the upload has advanced?
The object you use as a second argument uploaddata can pass a callback (onProgress) record. The Event– Object you receive contains the already loaded bytes.