-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
File downloads (streaming responses) #2230
Comments
Estimation meeting's discussion:
|
We can start by supporting only buffers in the first iteration. This is not enough for practical use though. For example, when accessing large data stored in an external storage container (see loopback-component-storage), we don't want to read the entire content into memory, but want to forward the readable stream returned by the outgoing request and write it to the incoming response. |
Is there any workaround to make stream response atm? |
You can inject the |
Is Response a wrapper for express? I see a similar functions exposed. I want to see if I could compress and send json content using the same approach. |
Discussing with @bajtos on the above comment, the code in the HomePageController that makes download possible are:
and
See full file in https://github.com/strongloop/loopback4-example-shopping/pull/16/files. |
@dhmlau @bajtos
When I try to execute this with the API explorer, I get the following message:
The following response headers are set:
Do you have any idea why this is not working? |
@RipkensLar, I found from swagger-api/swagger-ui#4250 that we should probably set the
Hope it helps. |
Thanks @dhmlau, that helped. I am able to download the pdf, but all pages are just blank. This could be a problem with loopback because I am able to download the exact same file in another project which is written in php but uses the same database. Edit:
This happens when I call my service which delivers me the file from the database. I double checked it in the php project and there I am able to use the data as it is, so I don't know why I get the error message that it is malformed. Edit2: |
@RipkensLar, i got the problem with empty file before, but after I switched to use |
|
@dhmlau But I am loading the pdf from a database, see explanation below:
But as stated above the pages remain blank. Calling the service in project A directly via browser give me the correct pdf. I also compared the raw data of the pdf and it is the same in the service in project A as well as in my controller in the loopback project. I suspect that OpenApi destroys the encoding when it sends the response, but I am running out of ideas. |
response.send(data) worked for me, thanks for the support. |
@dhmlau I just created a repo for you so you are able to see what is happening: Steps to reproduce: The pdf data which I use in the controller method is the data I receive from my php project api. |
@dhmlau do you have any updates on this? |
@hacksparrow sorry, with empty I meant that it is not displaying any content. Do you have any ideas how I could troubleshoot this? |
That's a PDF file format problem, so no idea. |
This looks like a character encoding (charset) problem to me.
|
@RipkensLar the PDF problem you have described is off topic here, can you please open a new issue please? |
Suggestion: Allow us to call out to the static file deliveryUse case: I have large files stored on the drive, but they are sensitive, so I don't want to use But I do want to take advantage of static's streaming and caching features. (For example it can also support HEAD requests for skipping to the middle of the content.) Example of how I might like to use it:
@authenticate('BearerStrategy')
@get('/documents/{filename}', {
async serveDocument(@param.path.string('filename') filename: string): Promise<void> {
if (await callerHasAccessTo(filename)) {
// Please give me a function serveStaticFile so that I can do this
return await serveStaticFile(path.join(storageFolder, filename), this.req);
} else {
throw new HttpErrors.NotFound('Nope');
}
} Loopback could help by providing this Update: I notice that |
Suggestion: Support caching when delivering from DBUse case: I have a large file in a repository, and I have also stored a checksum for it there. The client requests the file from our API, also passing an If the header value matches the stored checksum, that means the browser already has the file, and I can reply with Loopback can help either by:
Option 1 offers the most flexibility. But an implementation of number 2 might suit a majority of use cases. (If For anyone who wants this now, I had some success with: // Instead of a generated checksum, in this example I just use the document ID
const eTag = 'my-hash-' + fileDoc.id;
// Causes Chrome to cache for 1 month, during which it does not even make requests.
// After 1 month it makes If-None-Match requests, resulting in an efficient 304.
this.req.res!.setHeader('Cache-Control', `private, max-age=${31 * 24 * 60 * 60}`);
this.req.res!.setHeader('ETag', eTag); |
@bajtos Can you help me out with stubing Response parameter of the controller.(Any documentation or example) |
hi, Server is running at http://[::1]:3000 ** controller is, @get('/testfile', { Could you please help me to solve this. |
@Arathy-sivan , please provide a minimal application that exhibits the problem. This will help us investigate. Thank you. |
@Arathy-sivan , here is a recent example for uploading a sample : https://github.com/strongloop/loopback-next/tree/master/examples/file-upload . |
When I used this code I got the error, Unhandled error in POST /file-upload: 500 Error: unknown format "binary" is used in schema at path "#/properties/file" |
See #4834 (comment) |
Thank You soo much. It's working. |
To allow LB4 applications to implement file downloads, we need to make improvements in several areas:
Content-Disposition: attachment; filename="filename.jpg"
). This is already covered by the issue Configurable response types/formats #436.ReadableStream
andBuffer
too.res.download
provided by Express that will accept a file name and create an LB4 response object with all necessary fields correctly filled (content type, content disposition, body stream, etc.)Related issues:
The text was updated successfully, but these errors were encountered: