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
Send Buffer/binary response to client #800
Comments
Ok I finally managed to do it! The generated routes file already handles streams, you just have to return a valid readable stream. function returnHandler(response: any, statusCode?: number, data?: any, headers: any = {}) {
Object.keys(headers).forEach((name: string) => {
response.set(name, headers[name]);
});
if (data && typeof data.pipe === 'function' && data.readable && typeof data._read === 'function') {
// Here, data.pipe must be a function
data.pipe(response);
} else if (data || data === false) { // === false allows boolean result
response.status(statusCode || 200).json(data);
} else {
response.status(statusCode || 204).end();
}
} Controller: public async download(): Promise<fs.ReadStream> {
const filePath: string = '/path/to/file';
const fileName: string = 'doc.pdf';
const stat: fs.Stats = await fs.promises.stat(filePath);
this.setStatus(200);
this.setHeader('Content-Type', mime.lookup(filePath));
this.setHeader('Content-Length', stat.size.toString());
// Removing this line will cause to not launch the download, just serve the file as it
this.setHeader('Content-Disposition', `attachment; filename=${fileName}`);
return fs.createReadStream(filePath);
} The solution is more complicated than using
So the only way I found to fix this is to use Readable interface from stream : import { Readable } from 'stream';
// ...
public async download(): Promise<Readable> {
// ... The documentation is wrong but it works as needed. |
It does. I assume this affects the Express template only? |
Yes.
Here's an example of output from tsoa :) "/download": {
"get": {
"operationId": "downloadFile",
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"type": "string",
"format": "byte"
}
}
}
},
},
"description": "Download a file.",
"tags": [
"Download"
],
"security": [],
"parameters": []
}
}, |
This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days |
The title of this issue is a bit confusing, especially since it's resolved. From what I call tell looking at this line, pretty sure it only works when you return a |
Adding something like this to the default express template should fix it: import { Readable } from 'stream';
...
} else if (data instanceof Buffer) {
Readable.from(data).pipe(response); |
I dunno if this is related, but I saw the code for I'm using S3's return (
object
.Body
.transformToByteArray()
) When I do Instead, I had to modify the response this way: new FileService()
.get(
filename,
)
.then((
fileData
) => {
request
?.res
?.write(
fileData
)
request
?.res
?.end()
}) Is it possible there's something I'm missing that's not documented? There's a whole section on uploading files to tsoa (which works for me), but I'm missing the part about how to download files from tsoa. |
#435 and #44 were both closed but the issue is still here. Is there any way to send files to client using tsoa? Why doesn't
@Response
decorator exists ?Sorting
I'm submitting a ...
I confirm that I
Expected Behavior
Router to send file buffer to be downloaded by the client.
Current Behavior
When using Attempt 1: the file is sent but the file is invalid and cannot be opened.
When using Attempt 2:
Possible Solution
Steps to Reproduce
Attempt 1
Attempt 2
Context (Environment)
Version of the library: 3.3.0 (latest)
Version of NodeJS: v12.18.1
The text was updated successfully, but these errors were encountered: