SAP B1, Wie wird das von ItemImage abgerufene Bild angezeigt?

10

Ich rufe ein Bild von SAP B1 Service Layer ab. Beim Postboten kann ich es als image/pnganzeigen, aber es gibt ein Problem beim Anzeigen.

Was ist der richtige Weg, um es zu zeigen <img />?

require(fetchedImage) - funktioniert nicht


Ich habe eine Cloud-Funktion erstellt, um das Bild abzurufen und an den Client weiterzuleiten, bin mir jedoch nicht sicher, wie ich es tun soll.

Ein super komisches Objekt wie dieses zu haben

 data:
>     '�PNGörönöu001aönöu0000öu0000öu0000örIHDRöu0000öu.........

Ich weiß nicht, wie res.send(IMAGE IN PNG)ich es weitergeben soll, damit ich sehe, dass ich auf der Clientseite ein Bild bekomme.

Überprüfte base64Konvertierung, aber ich bin nicht sicher, wie ich sie verwenden soll.


Aktualisieren

Postbotenanfrage: (Dies funktioniert gut)

GET: https://su05.consensusintl.net/b1s/v1/ItemImages ('test') / $ value

Header : SessionId: FRAGEN SIE MICH, WENN SIE VERSUCHEN

Aus irgendeinem Grund können wir das Image nicht direkt im Front-End abrufen und müssen eine Middleware erstellen, damit wir es ausführen können Firebase Cloud Function

Hier ist also die Funktion, die das Bild abruft und nicht weiß, wie es übergeben werden soll.

Hier ist die Funktion in der Firebase Cloud-Funktion:

if (!req.body.productId) {
      res.status(400).send({ error: "productId is required" });
      return;
    }

    console.log("Starting the process");

    const productId = req.body.productId;

    const login = await Auth.login();
    const fetchedImg = await ItemMaster.getImage(login["SessionId"], productId);

    //Here in the fetchedImg, we're getting some data like
    res
      .status(200)
      .set("Content-Type", "image/png")
      .send(fetchedImg);

Und wir bekommen eine Antwort wie diese:

{Status: 200,

statusText: 'OK',

Überschriften:

{ server: 'nginx',

  date: 'Wed, 22 Jan 2020 03:52:22 GMT',

  'content-type': 'image/png',

  'transfer-encoding': 'chunked',

  connection: 'close',

  dataserviceversion: '3.0',

  'content-disposition': 'inline; filename="rr-96600.png"',

  vary: 'Accept-Encoding',

  'set-cookie': [ 'ROUTEID=.node2; path=/b1s' ] },

config:

{ url:

Daten:

' PNG \ r \ n \ u001a \ n \ u0000 \ u0000 \ u0000 \ rIHDR \ u0000 \ u0000 \ u0000 \ u0000 \ u0000 \ u0000 \ b \ u0002 \ u0000 \ u0000 \ u0000 \ u0006 \ u001fS \ u0000 \ u0000 \ u0000 \ u0019tEXtSoftware \ u0000Adobe ImageReadyq e <\ u0000 \ u0000 \ u0003hiTXtXML: com.adobe.xmp \ u0000 \ u0000 \ u0000 \ u0000 \ u0000

Dies ist super lang und geht für 80-100 weitere Zeilen

Wenn Sie testen möchten, können Sie Folgendes verwenden:

Briefträger:

POST: https://us-central1-rapid-replacement.cloudfunctions.net/getImageFromItems

body: {"productId": "test"}

Gültige Produkt-IDs sind: 1. "RR000102" 2. "Test" 3. "RR000101"

Dhaval Jardosh
quelle
1
Haben Sie den Inhaltstyp im Backend festgelegtres.set({'Content-Type': 'image/png'});
C.Gochev
1
Ja, das habe ich auch versucht, es gibt ein kaputtes Bild.
Dhaval Jardosh
1
Speichern Sie sie irgendwo?
C. Gochev
1
Nein, ich bin nicht, gibt es eine Möglichkeit, dies ohne das zu erreichen?
Dhaval Jardosh
1
Sie können es direkt const request = require('request')und in der Route vertretenrequest.get(url).pipe(res);
C.Gochev

Antworten:

4

Wenn Sie Bilder dynamisch verwenden möchten, müssen Sie die Bilder abrufen, sobald die Komponente bereitgestellt ist, und sie anschließend einfügen. Das abgerufene Bild sollte dann im Status der Komponente gespeichert und von dort in den src attrbut des img-Tags aufgenommen werden. Angenommen, Sie können das Bild bereits abrufen, sollte der folgende Code funktionieren.

import React, { Component } from "react";

export default class ComponentWithFetchedImage extends Component {
  constructor() {
    super();
    this.state = { image: undefined };   
  }

  componentDidMount() {
    let fetch_url = "https://picsum.photos/200";   // Insert your fetch url here
    fetch(fetch_url)
      .then(res => res.blob())
      .then(blob => URL.createObjectURL(blob))
      .then(url => this.setState({ image: url }))
      .catch(err => console.log(err));
  }

  render() {
    return (
      <div className="component">
        <img src={this.state.image} alt="" />
      </div>
    );   
  }
}
Taric
quelle
1
Ich kann nicht direkt in ComponentDidMount abrufen, da ich eine benutzerdefinierte Funktion auf der Serverseite erstellen muss und dies über die Cloud-Funktion mache.
Dhaval Jardosh
1
Es erlaubt mir nicht, auf Client-Seite abzurufen, es heißt, dass illegale Header in fetch / axios übergeben wurden, wenn ich es von React aus mache.
Dhaval Jardosh
3

Hier kommt eine funktionierende Lösung am nächsten, die ich gefunden habe. Grundsätzlich habe ich versucht, das Bild abzurufen und es dann in einen Blob auf dem Client objectURLumzuwandeln, damit Sie es in einen aktualisierten Code umwandeln können. Das Bild wird als Puffer gestreamt und auf dem Client verbraucht. Anschließend wird es in objectURL umgewandelt und dem Bild zugewiesen src

Servercode:

const http = require('http')
const axios = require('axios')
const fs = require('fs')
const stream = require('stream')
const server = http.createServer(function(req, res) {
  if (req.url === '/') {


    res.setHeader("Access-Control-Allow-Origin", "*");
    axios.post(
      "https://su05.consensusintl.net/b1s/v1/ItemImages('test')/$value", {
        responseType: "blob"
      }).then(function(resp) {
      console.log(resp.data)
      const buf_stream = new stream.PassThrough()
      buf_stream.end(Buffer.from(resp.data))
      buf_stream.pipe(res.end())
    }).catch(err => console.log(err))
  }
})


server.listen(3500)

Kundencode:

<!DOCTYPE html>
<html lang="en" dir="ltr">

<head>
  <meta charset="utf-8">
  <title></title>
</head>

<body>
  <img style="width:200px; height:200px" />
  <script>

  const img = document.getElementsByTagName("IMG")
  fetch('http://localhost:3500').then(function(response) {
    console.log(response)
    return response.body
  }).then(function(data) {
    console.log(data)
    const reader = data.getReader()
     return new ReadableStream({
    start(controller) {
      return pump();
      function pump() {
        return reader.read().then(({ done, value }) => {
          // When no more data needs to be consumed, close the stream
          if (done) {
              controller.close();
              return;
          }
          // Enqueue the next data chunk into our target stream
          controller.enqueue(value);
          return pump();
        });
      }
    }
  })
})
  .then(stream => new Response(stream))
  .then(response => response.blob())
  .then(blob => URL.createObjectURL(blob))
  .then(url => img[0].src = url)
  .catch(err => console.error(err));
    </script>
</body>

</html>
C. Gochev
quelle
Hey, eine Sache, die ich vergessen habe, dir zu sagen, dass ich hier ein Bild bekomme GET : https://su05.consensusintl.net/b1s/v1/ItemImages('test')/$value, aber wenn ich das Gleiche übergebe, funktioniert es nicht. Lassen Sie mich wissen, wenn Sie eine bessere Idee haben. Tut mir leid, wenn ich Sie störe.
Dhaval Jardosh
kleine Anerkennung von meiner Seite :)
Dhaval Jardosh
Siehe aktualisierten Code. Dies war mein letzter Versuch. Ich hoffe, Sie finden eine Lösung.
C. Gochev
0

Dieses Problem wurde behoben.

const getImage = async (sessionId, ItemCode) => {
  console.log("fetching image");
  let result = {};

  result = await axios.get(
    `${settings.url}${endpoints.ItemImages}('${ItemCode}')/$value`,
    { 
      headers: {Cookie: `B1SESSION=${sessionId}`},
      responseType: "arraybuffer" } 
    ).then(response => Buffer.from(response.data, 'binary').toString('base64'));

  //Here we're returning base64 value of Image
  return result;
};

So können wir das Bild auf der Clientseite mit sehen

<img src="data:image/png;base64,[BASE64-VALUE-HERE]"/>

Dhaval Jardosh
quelle