Eine URL mit Hilfe von GridFS DownloadToStream ersetzen

04/13/2021 13:59 emmoplayer#1
Hey alle zusammen.

Ich sitze seit Tagen an einem Problem was ich einfach nicht gelöst bekomme. :wutface:

Ich nutze MongoDB als meine Datenbank und speichere Bilder über GridFS ab.
Leider kriege ich nicht über MongoDB eine Art URL zu den Bildern, die über GridFS abgespeichert worden sind.

Gibt es eine Möglichkeit, mit Hilfe des DownloadToStream/OpenDownloadStream eine URL zu ersetzen?
Leider konnte ich bei den Java Drivern nichts passendes finden.

Vielen Dank im Voraus.
04/18/2021 23:45 elmarcia#2
Quote:
Originally Posted by emmoplayer View Post
Hey alle zusammen.

Ich sitze seit Tagen an einem Problem was ich einfach nicht gelöst bekomme. :wutface:

Ich nutze MongoDB als meine Datenbank und speichere Bilder über GridFS ab.
Leider kriege ich nicht über MongoDB eine Art URL zu den Bildern, die über GridFS abgespeichert worden sind.

Gibt es eine Möglichkeit, mit Hilfe des DownloadToStream/OpenDownloadStream eine URL zu ersetzen?
Leider konnte ich bei den Java Drivern nichts passendes finden.

Vielen Dank im Voraus.
I don't know what you mean by URL, im assuming you want your asset data url.

Code:
  // Obtain asset DATA url
    public String obtainFileUrl(GridFSBucket bucket, String fileNameOrId) {
        // open download stream
        GridFSDownloadStream downloadStream = bucket.openDownloadStream(fileNameOrId);
        // get file info, we need content type and file size
        GridFSFile file = downloadStream.getGridFSFile();
        // get content type
        org.bson.Document metadata = file.getMetadata();
        // if content type of asset is not stored as this key, change it
        String contentType = metadata.getString("contentType");
        // create byte buffer to read our stream
       // this can be bad if files are too big or memory is limited so be careful 
        byte[] raw = new byte[(int)file.getLength()];
        downloadStream.read(raw);
        downloadStream.close();
        // encode asset raw bytes to base64 string
        String base64EncodedAsset = Base64.getEncoder().encodeToString(raw);
        // create data url
        String url = String.format("data:%s;base64,%s", contentType, base64EncodedAsset);
        return url;
    }
This can be overhead if your api or whatever is consuming assets a lot.

Another solution: -> DownloadToStream to a file in a temp folder (with a hash or sth) and send back that file, every time a file needs to be consumed you check in your temp folder if a the file exits otherwise it creates the new one. (This strategy needs to flush unused files from time to time to prevent eating your disk space)
04/19/2021 14:08 emmoplayer#3
Hey @[Only registered and activated users can see links. Click Here To Register...].

Thank you for your efforts to explain both ways.
I took the second solution because the files could be really big.
04/20/2021 02:50 elmarcia#4
Quote:
Originally Posted by emmoplayer View Post
Hey @[Only registered and activated users can see links. Click Here To Register...].

Thank you for your efforts to explain both ways.
I took the second solution because the files could be really big.
Which framework are you using in your backend?,

Take into account that:
Code:
GridFSDownloadStream downloadStream = bucket.openDownloadStream(fileNameOrId);
Inherits InputStream so you can write your response in a way like this:

Example with Spring Boot
Code:
{
...
 try {

    InputStream is = downloadStream;
     response.setContentType(contentType);      
     response.setHeader("Content-Disposition", "attachment;filename=\"+file.getFilename​()+\""); 
     // copy it to response's OutputStream
      org.apache.commons.io.IOUtils.copy(is, response.getOutputStream());
      response.flushBuffer();
    } catch (IOException ex) {
      throw new RuntimeException("IOError writing file to output stream");
    }
As a third option, this will forward the stream without needing to store in disk.
04/20/2021 20:12 emmoplayer#5
@[Only registered and activated users can see links. Click Here To Register...]
I'm working without a special framework.

Quote:
As a third option, this will forward the stream without needing to store in disk.
Thanks!