Fail to upload file using QHttpMultipart to a nodejs server with multer
-
Hi Qt Community! I am actually experiencing a problem while trying to use QHttpMultipart to upload the file to a nodejs server using express and Multer. I am sure that the server is running properly, the problem might be on the QHttpMultipart side. Here is the code for my nodejs server and the QHttpMultipart upload part.
node server:const express = require('express'); const sqlite3 = require('sqlite3').verbose(); const multer = require('multer'); const app = express(); const upload = multer({ dest: './tmp/' }) app.use(express.static('.')); let db = new sqlite3.Database('./resources/files.sqlite'); app.get('/',(req, res)=>{ res.status(200).send("<form action=\"/upload\" enctype=\"multipart/form-data\" method=\"post\">\n" + " <div class=\"form-group\">\n" + " <input type=\"file\" class=\"form-control-file\" name=\"zip\">\n" + " <input type=\"submit\" value=\"Get me the stats!\" class=\"btn btn-default\">\n" + " </div>\n" + "</form>") }) app.get('/pcbs',(req,res) => { db.all("SELECT id, name, png, gerber, drill FROM PCBs LIMIT 30",[], (err, rows)=>{ if (err) throw err; res.json({ "pcbs": rows }) }) }) app.post('/upload',upload.single("zip"),(req,res,next)=>{ console.log(req); res.status(200).send("successfully uploaded the file!") }); const PORT = 4200; app.listen(PORT, ()=>{ console.log(`App running on port ${PORT}`); });
Here is the qt code:
QString file_path = QFileDialog::getOpenFileName(this, "Choose zip you want to upload",QDir::currentPath(),"Compressed File (*.zip)"); qDebug() << file_path; QNetworkRequest upload_request; upload_request.setUrl(urlBase + "upload"); QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType); QHttpPart zipPart; zipPart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("application/zip")); zipPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"zip\"")); QFile *file = new QFile(file_path); file->open(QIODevice::ReadOnly); zipPart.setBodyDevice(file); file->setParent(multiPart); // we cannot delete the file now, so delete it with the multiPart multiPart->append(zipPart); QNetworkAccessManager *upload_manager = new QNetworkAccessManager(this); QNetworkReply *reply = upload_manager->post(upload_request, multiPart); connect(upload_manager,&QNetworkAccessManager::finished,[this, reply,file](){ QString data = (QString)reply->readAll(); QJsonDocument jsonResponse = QJsonDocument::fromJson(data.toUtf8()); QJsonObject jsonObject = jsonResponse.object(); qDebug() << jsonObject["message"].toString(); file->close(); });
Any advice would be helpful! Thank you very much!
-
@never0lie
Looks like the only difference in the file part is the Content-Disposition header.
As you can see, the one from your successful upload isQVariant("form-data; name=\"zip\"; filename=\"3-half-bridges-board_drill.zip\"")
.
I'm not sure if this is the key part (to have a filename?) but you can start with that. -
In the beginning, I mentioned that the server is working properly. Here is the HTTP request printed from the node server when the file upload was working properly. I would post the request when using QHttpMultipart in a second post too due to character limit. I think the big difference is at the end around the body part:
IncomingMessage { _readableState: ReadableState { objectMode: false, highWaterMark: 16384, buffer: BufferList { head: null, tail: null, length: 0 }, length: 0, pipes: [], flowing: false, ended: true, endEmitted: true, reading: false, sync: false, needReadable: false, emittedReadable: false, readableListening: false, resumeScheduled: false, errorEmitted: false, emitClose: true, autoDestroy: false, destroyed: false, errored: null, closed: false, closeEmitted: false, defaultEncoding: 'utf8', awaitDrainWriters: null, multiAwaitDrain: false, readingMore: false, decoder: null, encoding: null, [Symbol(kPaused)]: true }, _events: [Object: null prototype] { end: [Function: clearRequestTimeout], readable: [Function: bound ] }, _eventsCount: 2, _maxListeners: undefined, socket: <ref *1> Socket { connecting: false, _hadError: false, _parent: null, _host: null, _readableState: ReadableState { objectMode: false, highWaterMark: 16384, buffer: BufferList { head: null, tail: null, length: 0 }, length: 0, pipes: [], flowing: true, ended: false, endEmitted: false, reading: true, sync: false, needReadable: true, emittedReadable: false, readableListening: false, resumeScheduled: false, errorEmitted: false, emitClose: false, autoDestroy: false, destroyed: false, errored: null, closed: false, closeEmitted: false, defaultEncoding: 'utf8', awaitDrainWriters: null, multiAwaitDrain: false, readingMore: false, decoder: null, encoding: null, [Symbol(kPaused)]: false }, _events: [Object: null prototype] { end: [Array], timeout: [Function: socketOnTimeout], data: [Function: bound socketOnData], error: [Function: socketOnError], close: [Array], drain: [Function: bound socketOnDrain], resume: [Function: onSocketResume], pause: [Function: onSocketPause] }, _eventsCount: 8, _maxListeners: undefined, _writableState: WritableState { objectMode: false, highWaterMark: 16384, finalCalled: false, needDrain: false, ending: false, ended: false, finished: false, destroyed: false, decodeStrings: false, defaultEncoding: 'utf8', length: 0, writing: false, corked: 0, sync: true, bufferProcessing: false, onwrite: [Function: bound onwrite], writecb: null, writelen: 0, afterWriteTickInfo: null, buffered: [], bufferedIndex: 0, allBuffers: true, allNoop: true, pendingcb: 0, prefinished: false, errorEmitted: false, emitClose: false, autoDestroy: false, errored: null, closed: false, closeEmitted: false }, allowHalfOpen: true, _sockname: null, _pendingData: null, _pendingEncoding: '', server: Server { maxHeaderSize: undefined, insecureHTTPParser: undefined, _events: [Object: null prototype], _eventsCount: 2, _maxListeners: undefined, _connections: 1, _handle: [TCP], _usingWorkers: false, _workers: [], _unref: false, allowHalfOpen: true, pauseOnConnect: false, httpAllowHalfOpen: false, timeout: 0, keepAliveTimeout: 5000, maxHeadersCount: null, headersTimeout: 60000, requestTimeout: 0, _connectionKey: '6::::4200', [Symbol(IncomingMessage)]: [Function: IncomingMessage], [Symbol(ServerResponse)]: [Function: ServerResponse], [Symbol(kCapture)]: false, [Symbol(async_id_symbol)]: 7 }, _server: Server { maxHeaderSize: undefined, insecureHTTPParser: undefined, _events: [Object: null prototype], _eventsCount: 2, _maxListeners: undefined, _connections: 1, _handle: [TCP], _usingWorkers: false, _workers: [], _unref: false, allowHalfOpen: true, pauseOnConnect: false, httpAllowHalfOpen: false, timeout: 0, keepAliveTimeout: 5000, maxHeadersCount: null, headersTimeout: 60000, requestTimeout: 0, _connectionKey: '6::::4200', [Symbol(IncomingMessage)]: [Function: IncomingMessage], [Symbol(ServerResponse)]: [Function: ServerResponse], [Symbol(kCapture)]: false, [Symbol(async_id_symbol)]: 7 }, parser: HTTPParser { '0': [Function: bound setRequestTimeout], '1': [Function: parserOnHeaders], '2': [Function: parserOnHeadersComplete], '3': [Function: parserOnBody], '4': [Function: parserOnMessageComplete], '5': [Function: bound onParserExecute], '6': [Function: bound onParserTimeout], _headers: [], _url: '', socket: [Circular *1], incoming: [Circular *2], outgoing: null, maxHeaderPairs: 2000, _consumed: true, onIncoming: [Function: bound parserOnIncoming], [Symbol(resource_symbol)]: [HTTPServerAsyncResource] }, on: [Function: socketListenerWrap], addListener: [Function: socketListenerWrap], prependListener: [Function: socketListenerWrap], _paused: false, _httpMessage: ServerResponse { _events: [Object: null prototype], _eventsCount: 1, _maxListeners: undefined, outputData: [], outputSize: 0, writable: true, destroyed: false, _last: false, chunkedEncoding: false, shouldKeepAlive: true, _defaultKeepAlive: true, useChunkedEncodingByDefault: true, sendDate: true, _removedConnection: false, _removedContLen: false, _removedTE: false, _contentLength: null, _hasBody: true, _trailer: '', finished: false, _headerSent: false, socket: [Circular *1], _header: null, _keepAliveTimeout: 5000, _onPendingData: [Function: bound updateOutgoingData], _sent100: false, _expect_continue: false, req: [Circular *2], locals: [Object: null prototype] {}, [Symbol(kCapture)]: false, [Symbol(kNeedDrain)]: false, [Symbol(corked)]: 0, [Symbol(kOutHeaders)]: [Object: null prototype] }, [Symbol(async_id_symbol)]: 10, [Symbol(kHandle)]: TCP { reading: true, onconnection: null, _consumed: true, [Symbol(owner_symbol)]: [Circular *1] }, [Symbol(kSetNoDelay)]: false, [Symbol(lastWriteQueueSize)]: 0, [Symbol(timeout)]: null, [Symbol(kBuffer)]: null, [Symbol(kBufferCb)]: null, [Symbol(kBufferGen)]: null, [Symbol(kCapture)]: false, [Symbol(kBytesRead)]: 0, [Symbol(kBytesWritten)]: 0, [Symbol(RequestTimeout)]: undefined }, httpVersionMajor: 1, httpVersionMinor: 1, httpVersion: '1.1', complete: true, headers: { host: 'localhost:4200', 'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:87.0) Gecko/20100101 Firefox/87.0', accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8', 'accept-language': 'en-US,en;q=0.5', 'accept-encoding': 'gzip, deflate', 'content-type': 'multipart/form-data; boundary=---------------------------385258764023582583331996931452', 'content-length': '1097', origin: 'http://localhost:4200', connection: 'keep-alive', referer: 'http://localhost:4200/', cookie: 'CSRF-Token-H6YUN=hAqmz6osDkzJ3QpLXETxettncrWx2siE; Webstorm-a8c8e774=5c7fc9b9-8e97-409a-9303-9bd6c54e8e00', 'upgrade-insecure-requests': '1' }, rawHeaders: [ 'Host', 'localhost:4200', 'User-Agent', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:87.0) Gecko/20100101 Firefox/87.0', 'Accept', 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8', 'Accept-Language', 'en-US,en;q=0.5', 'Accept-Encoding', 'gzip, deflate', 'Content-Type', 'multipart/form-data; boundary=---------------------------385258764023582583331996931452', 'Content-Length', '1097', 'Origin', 'http://localhost:4200', 'Connection', 'keep-alive', 'Referer', 'http://localhost:4200/', 'Cookie', 'CSRF-Token-H6YUN=hAqmz6osDkzJ3QpLXETxettncrWx2siE; Webstorm-a8c8e774=5c7fc9b9-8e97-409a-9303-9bd6c54e8e00', 'Upgrade-Insecure-Requests', '1' ], trailers: {}, rawTrailers: [], aborted: false, upgrade: false, url: '/upload', method: 'POST', statusCode: null, statusMessage: null, client: <ref *1> Socket { connecting: false, _hadError: false, _parent: null, _host: null, _readableState: ReadableState { objectMode: false, highWaterMark: 16384, buffer: BufferList { head: null, tail: null, length: 0 }, length: 0, pipes: [], flowing: true, ended: false, endEmitted: false, reading: true, sync: false, needReadable: true, emittedReadable: false, readableListening: false, resumeScheduled: false, errorEmitted: false, emitClose: false, autoDestroy: false, destroyed: false, errored: null, closed: false, closeEmitted: false, defaultEncoding: 'utf8', awaitDrainWriters: null, multiAwaitDrain: false, readingMore: false, decoder: null, encoding: null, [Symbol(kPaused)]: false }, _events: [Object: null prototype] { end: [Array], timeout: [Function: socketOnTimeout], data: [Function: bound socketOnData], error: [Function: socketOnError], close: [Array], drain: [Function: bound socketOnDrain], resume: [Function: onSocketResume], pause: [Function: onSocketPause] }, _eventsCount: 8, _maxListeners: undefined, _writableState: WritableState { objectMode: false, highWaterMark: 16384, finalCalled: false, needDrain: false, ending: false, ended: false, finished: false, destroyed: false, decodeStrings: false, defaultEncoding: 'utf8', length: 0, writing: false, corked: 0, sync: true, bufferProcessing: false, onwrite: [Function: bound onwrite], writecb: null, writelen: 0, afterWriteTickInfo: null, buffered: [], bufferedIndex: 0, allBuffers: true, allNoop: true, pendingcb: 0, prefinished: false, errorEmitted: false, emitClose: false, autoDestroy: false, errored: null, closed: false, closeEmitted: false }, allowHalfOpen: true, _sockname: null, _pendingData: null, _pendingEncoding: '', server: Server { maxHeaderSize: undefined, insecureHTTPParser: undefined, _events: [Object: null prototype], _eventsCount: 2, _maxListeners: undefined, _connections: 1, _handle: [TCP], _usingWorkers: false, _workers: [], _unref: false, allowHalfOpen: true, pauseOnConnect: false, httpAllowHalfOpen: false, timeout: 0, keepAliveTimeout: 5000, maxHeadersCount: null, headersTimeout: 60000, requestTimeout: 0, _connectionKey: '6::::4200', [Symbol(IncomingMessage)]: [Function: IncomingMessage], [Symbol(ServerResponse)]: [Function: ServerResponse], [Symbol(kCapture)]: false, [Symbol(async_id_symbol)]: 7 }, _server: Server { maxHeaderSize: undefined, insecureHTTPParser: undefined, _events: [Object: null prototype], _eventsCount: 2, _maxListeners: undefined, _connections: 1, _handle: [TCP], _usingWorkers: false, _workers: [], _unref: false, allowHalfOpen: true, pauseOnConnect: false, httpAllowHalfOpen: false, timeout: 0, keepAliveTimeout: 5000, maxHeadersCount: null, headersTimeout: 60000, requestTimeout: 0, _connectionKey: '6::::4200', [Symbol(IncomingMessage)]: [Function: IncomingMessage], [Symbol(ServerResponse)]: [Function: ServerResponse], [Symbol(kCapture)]: false, [Symbol(async_id_symbol)]: 7 }, parser: HTTPParser { '0': [Function: bound setRequestTimeout], '1': [Function: parserOnHeaders], '2': [Function: parserOnHeadersComplete], '3': [Function: parserOnBody], '4': [Function: parserOnMessageComplete], '5': [Function: bound onParserExecute], '6': [Function: bound onParserTimeout], _headers: [], _url: '', socket: [Circular *1], incoming: [Circular *2], outgoing: null, maxHeaderPairs: 2000, _consumed: true, onIncoming: [Function: bound parserOnIncoming], [Symbol(resource_symbol)]: [HTTPServerAsyncResource] }, on: [Function: socketListenerWrap], addListener: [Function: socketListenerWrap], prependListener: [Function: socketListenerWrap], _paused: false, _httpMessage: ServerResponse { _events: [Object: null prototype], _eventsCount: 1, _maxListeners: undefined, outputData: [], outputSize: 0, writable: true, destroyed: false, _last: false, chunkedEncoding: false, shouldKeepAlive: true, _defaultKeepAlive: true, useChunkedEncodingByDefault: true, sendDate: true, _removedConnection: false, _removedContLen: false, _removedTE: false, _contentLength: null, _hasBody: true, _trailer: '', finished: false, _headerSent: false, socket: [Circular *1], _header: null, _keepAliveTimeout: 5000, _onPendingData: [Function: bound updateOutgoingData], _sent100: false, _expect_continue: false, req: [Circular *2], locals: [Object: null prototype] {}, [Symbol(kCapture)]: false, [Symbol(kNeedDrain)]: false, [Symbol(corked)]: 0, [Symbol(kOutHeaders)]: [Object: null prototype] }, [Symbol(async_id_symbol)]: 10, [Symbol(kHandle)]: TCP { reading: true, onconnection: null, _consumed: true, [Symbol(owner_symbol)]: [Circular *1] }, [Symbol(kSetNoDelay)]: false, [Symbol(lastWriteQueueSize)]: 0, [Symbol(timeout)]: null, [Symbol(kBuffer)]: null, [Symbol(kBufferCb)]: null, [Symbol(kBufferGen)]: null, [Symbol(kCapture)]: false, [Symbol(kBytesRead)]: 0, [Symbol(kBytesWritten)]: 0, [Symbol(RequestTimeout)]: undefined }, _consuming: true, _dumped: false, next: [Function: next], baseUrl: '', originalUrl: '/upload', _parsedUrl: Url { protocol: null, slashes: null, auth: null, host: null, port: null, hostname: null, hash: null, search: null, query: null, pathname: '/upload', path: '/upload', href: '/upload', _raw: '/upload' }, params: {}, query: {}, res: <ref *3> ServerResponse { _events: [Object: null prototype] { finish: [Function: bound resOnFinish] }, _eventsCount: 1, _maxListeners: undefined, outputData: [], outputSize: 0, writable: true, destroyed: false, _last: false, chunkedEncoding: false, shouldKeepAlive: true, _defaultKeepAlive: true, useChunkedEncodingByDefault: true, sendDate: true, _removedConnection: false, _removedContLen: false, _removedTE: false, _contentLength: null, _hasBody: true, _trailer: '', finished: false, _headerSent: false, socket: <ref *1> Socket { connecting: false, _hadError: false, _parent: null, _host: null, _readableState: [ReadableState], _events: [Object: null prototype], _eventsCount: 8, _maxListeners: undefined, _writableState: [WritableState], allowHalfOpen: true, _sockname: null, _pendingData: null, _pendingEncoding: '', server: [Server], _server: [Server], parser: [HTTPParser], on: [Function: socketListenerWrap], addListener: [Function: socketListenerWrap], prependListener: [Function: socketListenerWrap], _paused: false, _httpMessage: [Circular *3], [Symbol(async_id_symbol)]: 10, [Symbol(kHandle)]: [TCP], [Symbol(kSetNoDelay)]: false, [Symbol(lastWriteQueueSize)]: 0, [Symbol(timeout)]: null, [Symbol(kBuffer)]: null, [Symbol(kBufferCb)]: null, [Symbol(kBufferGen)]: null, [Symbol(kCapture)]: false, [Symbol(kBytesRead)]: 0, [Symbol(kBytesWritten)]: 0, [Symbol(RequestTimeout)]: undefined }, _header: null, _keepAliveTimeout: 5000, _onPendingData: [Function: bound updateOutgoingData], _sent100: false, _expect_continue: false, req: [Circular *2], locals: [Object: null prototype] {}, [Symbol(kCapture)]: false, [Symbol(kNeedDrain)]: false, [Symbol(corked)]: 0, [Symbol(kOutHeaders)]: [Object: null prototype] { 'x-powered-by': [Array] } }, route: Route { path: '/upload', stack: [ [Layer], [Layer] ], methods: { post: true } }, body: [Object: null prototype] {}, file: { fieldname: 'zip', originalname: '3-half-bridges-board_drill.zip', encoding: '7bit', mimetype: 'application/zip', destination: './tmp/', filename: '13289ddcca83407a7770faeda5bd62a4', path: 'tmp/13289ddcca83407a7770faeda5bd62a4', size: 851 }, [Symbol(kCapture)]: false, [Symbol(RequestTimeout)]: undefined }
-
here is the request printed from node when I use QHttpMultipart:
IncomingMessage { _readableState: ReadableState { objectMode: false, highWaterMark: 16384, buffer: BufferList { head: null, tail: null, length: 0 }, length: 0, pipes: [], flowing: false, ended: true, endEmitted: true, reading: false, sync: false, needReadable: false, emittedReadable: false, readableListening: true, resumeScheduled: false, errorEmitted: false, emitClose: true, autoDestroy: false, destroyed: false, errored: null, closed: false, closeEmitted: false, defaultEncoding: 'utf8', awaitDrainWriters: null, multiAwaitDrain: false, readingMore: false, decoder: null, encoding: null, [Symbol(kPaused)]: true }, _events: [Object: null prototype] { end: [Function: clearRequestTimeout], readable: [Function: bound ] }, _eventsCount: 2, _maxListeners: undefined, socket: <ref *1> Socket { connecting: false, _hadError: false, _parent: null, _host: null, _readableState: ReadableState { objectMode: false, highWaterMark: 16384, buffer: BufferList { head: null, tail: null, length: 0 }, length: 0, pipes: [], flowing: true, ended: false, endEmitted: false, reading: true, sync: false, needReadable: true, emittedReadable: false, readableListening: false, resumeScheduled: false, errorEmitted: false, emitClose: false, autoDestroy: false, destroyed: false, errored: null, closed: false, closeEmitted: false, defaultEncoding: 'utf8', awaitDrainWriters: null, multiAwaitDrain: false, readingMore: false, decoder: null, encoding: null, [Symbol(kPaused)]: false }, _events: [Object: null prototype] { end: [Array], timeout: [Function: socketOnTimeout], data: [Function: bound socketOnData], error: [Function: socketOnError], close: [Array], drain: [Function: bound socketOnDrain], resume: [Function: onSocketResume], pause: [Function: onSocketPause] }, _eventsCount: 8, _maxListeners: undefined, _writableState: WritableState { objectMode: false, highWaterMark: 16384, finalCalled: false, needDrain: false, ending: false, ended: false, finished: false, destroyed: false, decodeStrings: false, defaultEncoding: 'utf8', length: 0, writing: false, corked: 0, sync: true, bufferProcessing: false, onwrite: [Function: bound onwrite], writecb: null, writelen: 0, afterWriteTickInfo: null, buffered: [], bufferedIndex: 0, allBuffers: true, allNoop: true, pendingcb: 0, prefinished: false, errorEmitted: false, emitClose: false, autoDestroy: false, errored: null, closed: false, closeEmitted: false }, allowHalfOpen: true, _sockname: null, _pendingData: null, _pendingEncoding: '', server: Server { maxHeaderSize: undefined, insecureHTTPParser: undefined, _events: [Object: null prototype], _eventsCount: 2, _maxListeners: undefined, _connections: 1, _handle: [TCP], _usingWorkers: false, _workers: [], _unref: false, allowHalfOpen: true, pauseOnConnect: false, httpAllowHalfOpen: false, timeout: 0, keepAliveTimeout: 5000, maxHeadersCount: null, headersTimeout: 60000, requestTimeout: 0, _connectionKey: '6::::4200', [Symbol(IncomingMessage)]: [Function: IncomingMessage], [Symbol(ServerResponse)]: [Function: ServerResponse], [Symbol(kCapture)]: false, [Symbol(async_id_symbol)]: 7 }, _server: Server { maxHeaderSize: undefined, insecureHTTPParser: undefined, _events: [Object: null prototype], _eventsCount: 2, _maxListeners: undefined, _connections: 1, _handle: [TCP], _usingWorkers: false, _workers: [], _unref: false, allowHalfOpen: true, pauseOnConnect: false, httpAllowHalfOpen: false, timeout: 0, keepAliveTimeout: 5000, maxHeadersCount: null, headersTimeout: 60000, requestTimeout: 0, _connectionKey: '6::::4200', [Symbol(IncomingMessage)]: [Function: IncomingMessage], [Symbol(ServerResponse)]: [Function: ServerResponse], [Symbol(kCapture)]: false, [Symbol(async_id_symbol)]: 7 }, parser: HTTPParser { '0': [Function: bound setRequestTimeout], '1': [Function: parserOnHeaders], '2': [Function: parserOnHeadersComplete], '3': [Function: parserOnBody], '4': [Function: parserOnMessageComplete], '5': [Function: bound onParserExecute], '6': [Function: bound onParserTimeout], _headers: [], _url: '', socket: [Circular *1], incoming: [Circular *2], outgoing: null, maxHeaderPairs: 2000, _consumed: true, onIncoming: [Function: bound parserOnIncoming], [Symbol(resource_symbol)]: [HTTPServerAsyncResource] }, on: [Function: socketListenerWrap], addListener: [Function: socketListenerWrap], prependListener: [Function: socketListenerWrap], _paused: false, _httpMessage: ServerResponse { _events: [Object: null prototype], _eventsCount: 1, _maxListeners: undefined, outputData: [], outputSize: 0, writable: true, destroyed: false, _last: false, chunkedEncoding: false, shouldKeepAlive: true, _defaultKeepAlive: true, useChunkedEncodingByDefault: true, sendDate: true, _removedConnection: false, _removedContLen: false, _removedTE: false, _contentLength: null, _hasBody: true, _trailer: '', finished: false, _headerSent: false, socket: [Circular *1], _header: null, _keepAliveTimeout: 5000, _onPendingData: [Function: bound updateOutgoingData], _sent100: false, _expect_continue: false, req: [Circular *2], locals: [Object: null prototype] {}, [Symbol(kCapture)]: false, [Symbol(kNeedDrain)]: false, [Symbol(corked)]: 0, [Symbol(kOutHeaders)]: [Object: null prototype] }, [Symbol(async_id_symbol)]: 10, [Symbol(kHandle)]: TCP { reading: true, onconnection: null, _consumed: true, [Symbol(owner_symbol)]: [Circular *1] }, [Symbol(kSetNoDelay)]: false, [Symbol(lastWriteQueueSize)]: 0, [Symbol(timeout)]: null, [Symbol(kBuffer)]: null, [Symbol(kBufferCb)]: null, [Symbol(kBufferGen)]: null, [Symbol(kCapture)]: false, [Symbol(kBytesRead)]: 0, [Symbol(kBytesWritten)]: 0, [Symbol(RequestTimeout)]: undefined }, httpVersionMajor: 1, httpVersionMinor: 1, httpVersion: '1.1', complete: true, headers: { host: 'localhost:4200', 'content-type': 'multipart/form-data; boundary="boundary_.oOo._gNCCVxxFwI3s+FNvVPGkoG7tAe6t6s+Y"', 'mime-version': '1.0', 'content-length': '1034', connection: 'Keep-Alive', 'accept-encoding': 'gzip, deflate', 'accept-language': 'en-US,*', 'user-agent': 'Mozilla/5.0' }, rawHeaders: [ 'Host', 'localhost:4200', 'Content-Type', 'multipart/form-data; boundary="boundary_.oOo._gNCCVxxFwI3s+FNvVPGkoG7tAe6t6s+Y"', 'MIME-Version', '1.0', 'Content-Length', '1034', 'Connection', 'Keep-Alive', 'Accept-Encoding', 'gzip, deflate', 'Accept-Language', 'en-US,*', 'User-Agent', 'Mozilla/5.0' ], trailers: {}, rawTrailers: [], aborted: false, upgrade: false, url: '/upload', method: 'POST', statusCode: null, statusMessage: null, client: <ref *1> Socket { connecting: false, _hadError: false, _parent: null, _host: null, _readableState: ReadableState { objectMode: false, highWaterMark: 16384, buffer: BufferList { head: null, tail: null, length: 0 }, length: 0, pipes: [], flowing: true, ended: false, endEmitted: false, reading: true, sync: false, needReadable: true, emittedReadable: false, readableListening: false, resumeScheduled: false, errorEmitted: false, emitClose: false, autoDestroy: false, destroyed: false, errored: null, closed: false, closeEmitted: false, defaultEncoding: 'utf8', awaitDrainWriters: null, multiAwaitDrain: false, readingMore: false, decoder: null, encoding: null, [Symbol(kPaused)]: false }, _events: [Object: null prototype] { end: [Array], timeout: [Function: socketOnTimeout], data: [Function: bound socketOnData], error: [Function: socketOnError], close: [Array], drain: [Function: bound socketOnDrain], resume: [Function: onSocketResume], pause: [Function: onSocketPause] }, _eventsCount: 8, _maxListeners: undefined, _writableState: WritableState { objectMode: false, highWaterMark: 16384, finalCalled: false, needDrain: false, ending: false, ended: false, finished: false, destroyed: false, decodeStrings: false, defaultEncoding: 'utf8', length: 0, writing: false, corked: 0, sync: true, bufferProcessing: false, onwrite: [Function: bound onwrite], writecb: null, writelen: 0, afterWriteTickInfo: null, buffered: [], bufferedIndex: 0, allBuffers: true, allNoop: true, pendingcb: 0, prefinished: false, errorEmitted: false, emitClose: false, autoDestroy: false, errored: null, closed: false, closeEmitted: false }, allowHalfOpen: true, _sockname: null, _pendingData: null, _pendingEncoding: '', server: Server { maxHeaderSize: undefined, insecureHTTPParser: undefined, _events: [Object: null prototype], _eventsCount: 2, _maxListeners: undefined, _connections: 1, _handle: [TCP], _usingWorkers: false, _workers: [], _unref: false, allowHalfOpen: true, pauseOnConnect: false, httpAllowHalfOpen: false, timeout: 0, keepAliveTimeout: 5000, maxHeadersCount: null, headersTimeout: 60000, requestTimeout: 0, _connectionKey: '6::::4200', [Symbol(IncomingMessage)]: [Function: IncomingMessage], [Symbol(ServerResponse)]: [Function: ServerResponse], [Symbol(kCapture)]: false, [Symbol(async_id_symbol)]: 7 }, _server: Server { maxHeaderSize: undefined, insecureHTTPParser: undefined, _events: [Object: null prototype], _eventsCount: 2, _maxListeners: undefined, _connections: 1, _handle: [TCP], _usingWorkers: false, _workers: [], _unref: false, allowHalfOpen: true, pauseOnConnect: false, httpAllowHalfOpen: false, timeout: 0, keepAliveTimeout: 5000, maxHeadersCount: null, headersTimeout: 60000, requestTimeout: 0, _connectionKey: '6::::4200', [Symbol(IncomingMessage)]: [Function: IncomingMessage], [Symbol(ServerResponse)]: [Function: ServerResponse], [Symbol(kCapture)]: false, [Symbol(async_id_symbol)]: 7 }, parser: HTTPParser { '0': [Function: bound setRequestTimeout], '1': [Function: parserOnHeaders], '2': [Function: parserOnHeadersComplete], '3': [Function: parserOnBody], '4': [Function: parserOnMessageComplete], '5': [Function: bound onParserExecute], '6': [Function: bound onParserTimeout], _headers: [], _url: '', socket: [Circular *1], incoming: [Circular *2], outgoing: null, maxHeaderPairs: 2000, _consumed: true, onIncoming: [Function: bound parserOnIncoming], [Symbol(resource_symbol)]: [HTTPServerAsyncResource] }, on: [Function: socketListenerWrap], addListener: [Function: socketListenerWrap], prependListener: [Function: socketListenerWrap], _paused: false, _httpMessage: ServerResponse { _events: [Object: null prototype], _eventsCount: 1, _maxListeners: undefined, outputData: [], outputSize: 0, writable: true, destroyed: false, _last: false, chunkedEncoding: false, shouldKeepAlive: true, _defaultKeepAlive: true, useChunkedEncodingByDefault: true, sendDate: true, _removedConnection: false, _removedContLen: false, _removedTE: false, _contentLength: null, _hasBody: true, _trailer: '', finished: false, _headerSent: false, socket: [Circular *1], _header: null, _keepAliveTimeout: 5000, _onPendingData: [Function: bound updateOutgoingData], _sent100: false, _expect_continue: false, req: [Circular *2], locals: [Object: null prototype] {}, [Symbol(kCapture)]: false, [Symbol(kNeedDrain)]: false, [Symbol(corked)]: 0, [Symbol(kOutHeaders)]: [Object: null prototype] }, [Symbol(async_id_symbol)]: 10, [Symbol(kHandle)]: TCP { reading: true, onconnection: null, _consumed: true, [Symbol(owner_symbol)]: [Circular *1] }, [Symbol(kSetNoDelay)]: false, [Symbol(lastWriteQueueSize)]: 0, [Symbol(timeout)]: null, [Symbol(kBuffer)]: null, [Symbol(kBufferCb)]: null, [Symbol(kBufferGen)]: null, [Symbol(kCapture)]: false, [Symbol(kBytesRead)]: 0, [Symbol(kBytesWritten)]: 0, [Symbol(RequestTimeout)]: undefined }, _consuming: true, _dumped: false, next: [Function: next], baseUrl: '', originalUrl: '/upload', _parsedUrl: Url { protocol: null, slashes: null, auth: null, host: null, port: null, hostname: null, hash: null, search: null, query: null, pathname: '/upload', path: '/upload', href: '/upload', _raw: '/upload' }, params: {}, query: {}, res: <ref *3> ServerResponse { _events: [Object: null prototype] { finish: [Function: bound resOnFinish] }, _eventsCount: 1, _maxListeners: undefined, outputData: [], outputSize: 0, writable: true, destroyed: false, _last: false, chunkedEncoding: false, shouldKeepAlive: true, _defaultKeepAlive: true, useChunkedEncodingByDefault: true, sendDate: true, _removedConnection: false, _removedContLen: false, _removedTE: false, _contentLength: null, _hasBody: true, _trailer: '', finished: false, _headerSent: false, socket: <ref *1> Socket { connecting: false, _hadError: false, _parent: null, _host: null, _readableState: [ReadableState], _events: [Object: null prototype], _eventsCount: 8, _maxListeners: undefined, _writableState: [WritableState], allowHalfOpen: true, _sockname: null, _pendingData: null, _pendingEncoding: '', server: [Server], _server: [Server], parser: [HTTPParser], on: [Function: socketListenerWrap], addListener: [Function: socketListenerWrap], prependListener: [Function: socketListenerWrap], _paused: false, _httpMessage: [Circular *3], [Symbol(async_id_symbol)]: 10, [Symbol(kHandle)]: [TCP], [Symbol(kSetNoDelay)]: false, [Symbol(lastWriteQueueSize)]: 0, [Symbol(timeout)]: null, [Symbol(kBuffer)]: null, [Symbol(kBufferCb)]: null, [Symbol(kBufferGen)]: null, [Symbol(kCapture)]: false, [Symbol(kBytesRead)]: 0, [Symbol(kBytesWritten)]: 0, [Symbol(RequestTimeout)]: undefined }, _header: null, _keepAliveTimeout: 5000, _onPendingData: [Function: bound updateOutgoingData], _sent100: false, _expect_continue: false, req: [Circular *2], locals: [Object: null prototype] {}, [Symbol(kCapture)]: false, [Symbol(kNeedDrain)]: false, [Symbol(corked)]: 0, [Symbol(kOutHeaders)]: [Object: null prototype] { 'x-powered-by': [Array] } }, route: Route { path: '/upload', stack: [ [Layer], [Layer] ], methods: { post: true } }, body: [Object: null prototype] { zip: 'PK\x03\x04\x14\x00\x00\x00\x00\x00\x04z\x0BIJH\x18"�\x02\x00\x00�\x02\x00\x007\x00\x00\x00358f7f9cd50126e4_14709282650000_drills-plated-all.drillM48\r\n' + 'M71,TZ\r\n' + 'FMAT,2\r\n' + 'T1C0.635\r\n' + 'T2C1.15\r\n' + 'T3C1.4\r\n' + 'T4C3.0\r\n' + '%\r\n' + 'T1\r\n' + 'X10.8Y20.725\r\n' + 'X2.3Y3.7\r\n' + 'X40.15Y20.05\r\n' + 'X51.7Y22.0\r\n' + 'X25.15Y3.7\r\n' + 'X28.85Y22.0\r\n' + 'X48.0Y3.7\r\n' + 'X-12.05Y20.725\r\n' + 'X33.65Y20.725\r\n' + 'X-7.55Y24.364645\r\n' + 'X6.0Y22.0\r\n' + 'X17.3Y20.05\r\n' + 'X15.3Y24.364645\r\n' + 'X-5.55Y20.05\r\n' + 'X38.15Y24.364645\r\n' + 'T2\r\n' + 'X51.755Y1.225\r\n' + 'X49.215Y1.225\r\n' + 'X46.675Y1.225\r\n' + 'X44.135Y1.225\r\n' + 'X41.595Y1.225\r\n' + 'X28.905Y1.225\r\n' + 'X26.365Y1.225\r\n' + 'X23.825Y1.225\r\n' + 'X21.285Y1.225\r\n' + 'X18.745Y1.225\r\n' + 'X6.055Y1.225\r\n' + 'X3.515Y1.225\r\n' + 'X0.975Y1.225\r\n' + 'X-1.565Y1.225\r\n' + 'X-4.105Y1.225\r\n' + 'T3\r\n' + 'X35.375Y2.525\r\n' + 'X35.375Y7.525\r\n' + 'X-10.325Y2.525\r\n' + 'X-10.325Y7.525\r\n' + 'X12.525Y2.525\r\n' + 'X12.525Y7.525\r\n' + 'T4\r\n' + 'X45.8Y29.2\r\n' + 'X22.95Y29.2\r\n' + 'X0.1Y29.2\r\n' + 'T00\r\n' + 'M30\r\n' + 'PK\x01\x02\x14\x03\x14\x00\x00\x00\x00\x00\x04z\x0BIJH\x18"�\x02\x00\x00�\x02\x00\x007\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00��\x00\x00\x00\x00358f7f9cd50126e4_14709282650000_drills-plated-all.drillPK\x05\x06\x00\x00\x00\x00\x01\x00\x01\x00e\x00\x00\x00�\x02\x00\x00\x00\x00' }, __onFinished: null, [Symbol(kCapture)]: false, [Symbol(RequestTimeout)]: undefined }
-
@Bonnie Thank you for your advice! I tried that however it didn't work. The only difference is that the beginning part of the last body field changed from
body: [Object: null prototype] { zip: 'PK\x03\x04\x14\x00\x00\x00\x00\x00\x04z\x0BIJH\x18"�\x02\x00\x00�\x02\x00\x007\x00\x00\x00358f7f9cd50126e4_14709282650000_drills-plated-all.drillM48\r\n' + 'M71,TZ\r\n' +
to
body: [Object: null prototype] { file: 'PK\x03\x04\x14\x00\x00\x00\x00\x00\x04z\x0BIJH\x18"�\x02\x00\x00�\x02\x00\x007\x00\x00\x00358f7f9cd50126e4_14709282650000_drills-plated-all.drillM48\r\n' +
and the file upload still fails.
I just realized there is a major difference in the successful upload, the successful body part looks likebody: [Object: null prototype] {}, file: { fieldname: 'zip', originalname: '3-half-bridges-board_drill.zip', encoding: '7bit', mimetype: 'application/zip', destination: './tmp/', filename: '13289ddcca83407a7770faeda5bd62a4', path: 'tmp/13289ddcca83407a7770faeda5bd62a4', size: 851 },
I don't know why this happens. Can someone explain? Thanks!
-
@never0lie
Oh, ok, I didn't read your code and log carefully enough, that's just my working code for some server...I may need to take it back...
Your successful upload seems to have an empty body, but with QHttpPart, the data should always go to the body.
Is there any way to print the raw / unparsed data? -
@Bonnie Okay I think I got the raw data. Correct me if I am wrong.
Successful upload:POST /upload HTTP/1.1 Host: localhost:4200 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:87.0) Gecko/20100101 Firefox/87.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate Content-Type: multipart/form-data; boundary=---------------------------4841422831862908953042778266 Content-Length: 1093 Origin: http://localhost:4200 Referer: http://localhost:4200/ Upgrade-Insecure-Requests: 1 Connection: keep-alive -----------------------------4841422831862908953042778266 Content-Disposition: form-data; name="zip"; filename="3-half-bridges-board_drill.zip" Content-Type: application/zip PK�����zIJH"����7���358f7f9cd50126e4_14709282650000_drills-plated-all.drillM48 M71,TZ FMAT,2 T1C0.635 T2C1.15 T3C1.4 T4C3.0 % T1 X10.8Y20.725 X2.3Y3.7 X40.15Y20.05 X51.7Y22.0 X25.15Y3.7 X28.85Y22.0 X48.0Y3.7 X-12.05Y20.725 X33.65Y20.725 X-7.55Y24.364645 X6.0Y22.0 X17.3Y20.05 X15.3Y24.364645 X-5.55Y20.05 X38.15Y24.364645 T2 X51.755Y1.225 X49.215Y1.225 X46.675Y1.225 X44.135Y1.225 X41.595Y1.225 X28.905Y1.225 X26.365Y1.225 X23.825Y1.225 X21.285Y1.225 X18.745Y1.225 X6.055Y1.225 X3.515Y1.225 X0.975Y1.225 X-1.565Y1.225 X-4.105Y1.225 T3 X35.375Y2.525 X35.375Y7.525 X-10.325Y2.525 X-10.325Y7.525 X12.525Y2.525 X12.525Y7.525 T4 X45.8Y29.2 X22.95Y29.2 X0.1Y29.2 T00 M30 PK�����zIJH"����7�����������¤����358f7f9cd50126e4_14709282650000_drills-plated-all.drillPK������e���Ø���� -----------------------------4841422831862908953042778266--
from QHttpMultiPart
POST /upload HTTP/1.1 Host: localhost:4200 Content-Type: multipart/form-data; boundary="boundary_.oOo._PFFay6bRVYznGcyiqa8QpglQGLAQk7Zh" MIME-Version: 1.0 Content-Length: 1052 Accept-Encoding: gzip, deflate Accept-Language: en-US,* User-Agent: Mozilla/5.0 Connection: keep-alive --boundary_.oOo._PFFay6bRVYznGcyiqa8QpglQGLAQk7Zh Content-Type: application/zip Content-Disposition: form-data; name="file"; fieldname="zip" PK�����zIJH"����7���358f7f9cd50126e4_14709282650000_drills-plated-all.drillM48 M71,TZ FMAT,2 T1C0.635 T2C1.15 T3C1.4 T4C3.0 % T1 X10.8Y20.725 X2.3Y3.7 X40.15Y20.05 X51.7Y22.0 X25.15Y3.7 X28.85Y22.0 X48.0Y3.7 X-12.05Y20.725 X33.65Y20.725 X-7.55Y24.364645 X6.0Y22.0 X17.3Y20.05 X15.3Y24.364645 X-5.55Y20.05 X38.15Y24.364645 T2 X51.755Y1.225 X49.215Y1.225 X46.675Y1.225 X44.135Y1.225 X41.595Y1.225 X28.905Y1.225 X26.365Y1.225 X23.825Y1.225 X21.285Y1.225 X18.745Y1.225 X6.055Y1.225 X3.515Y1.225 X0.975Y1.225 X-1.565Y1.225 X-4.105Y1.225 T3 X35.375Y2.525 X35.375Y7.525 X-10.325Y2.525 X-10.325Y7.525 X12.525Y2.525 X12.525Y7.525 T4 X45.8Y29.2 X22.95Y29.2 X0.1Y29.2 T00 M30 PK�����zIJH"����7�����������¤����358f7f9cd50126e4_14709282650000_drills-plated-all.drillPK������e���Ø���� --boundary_.oOo._PFFay6bRVYznGcyiqa8QpglQGLAQk7Zh--
I hope this info would be helpful. Thanks again!
-
@never0lie
Looks like the only difference in the file part is the Content-Disposition header.
As you can see, the one from your successful upload isQVariant("form-data; name=\"zip\"; filename=\"3-half-bridges-board_drill.zip\"")
.
I'm not sure if this is the key part (to have a filename?) but you can start with that.