简体   繁体   English

如何使用redux-observable正确获取二进制图像?

[英]How to GET binary image correctly using redux-observable?

I am trying to GET image using redux-observable. 我试图使用redux-observable获取图像。

Based on Microsoft Graph API , it returns binary data of the requested photo. 基于Microsoft Graph API ,它返回所请求照片的二进制数据。

I succeed getting the image using Postman (it shows the image in the result since it is binary). 我成功使用Postman获取图像(它显示结果中的图像,因为它是二进制)。

However, when I try to use redux-observable , response I got is always null , and responseType is always json no matter what I give for Content-Type like image/jpeg , text/plain , application/json . 但是,当我尝试使用redux-observable时 ,我得到的响应总是为null ,并且无论我为Content-Type提供什么样的响应,它都是jsonimage/jpegtext/plainapplication/json

export const getAvatarEpic = (action$, store) =>
  action$
    .ofType(GET_AVATAR)
    .mergeMap(action =>
      ajax
        .get(
          'https://graph.microsoft.com/v1.0/me/photo/$value',
          {
            // 'Content-Type': 'image/jpeg',
            'Authorization': 'Bearer ' + myToken
          }
        )
        .do(res => console.log(res))  // <- the result
        .map(getAvatarSucceed)
        .catch(getAvatarFailed)
    );

Here is what I got. 这就是我得到的。 Maybe I should use something else instead of ajax.get ? 也许我应该使用别的东西而不是ajax.get

{
  "originalEvent": {
    "isTrusted": true
  },
  "xhr": {},
  "request": {
    "async": true,
    "crossDomain": false,
    "withCredentials": false,
    "headers": {
      "Authorization": "Bearer hereIsMyToken",
      "X-Requested-With": "XMLHttpRequest"
    },
    "method": "GET",
    "responseType": "json",
    "timeout": 0,
    "url": "https://graph.microsoft.com/v1.0/me/photo/$value"
  },
  "status": 200,
  "responseType": "json",
  "response": null
}

I want to first make sure it becomes clear that redux-observable and RxJS are separate things. 我想首先确保redux-observable和RxJS是分开的东西。 This question is actually an RxJS question, as is nearly all questions you'll come across (even when using redux-observable) since redux-observable is small and really defers almost everything to idiomatic Rx. 这个问题实际上是一个RxJS问题,因为几乎所有你会遇到的问题(即使使用redux-observable)也是如此,因为redux-observable很小,并且几乎把所有东西都推迟到惯用的Rx。 This is important because when asking questions if you present and phrase them as just Rx questions you'll find much more help and resources since it's a larger community overall. 这一点很重要,因为在提问时如果你提出问题并将它们简称为Rx问题,你会发现更多的帮助和资源,因为它是一个更大的社区。 Hope this helps! 希望这可以帮助!


If you're using the built-in ajax utilities for RxJS v5, you'll need to use the regular ajax() helper, not the shorthand ajax.get() one. 如果您正在为RxJS v5使用内置的ajax实用程序,则需要使用常规的ajax()帮助程序,而不是简写的ajax.get()

Then you can provide responseType: 'arraybuffer' to get the image as a binary data: 然后你可以提供responseType: 'arraybuffer'来获取图像作为二进制数据:

export const getAvatarEpic = (action$, store) =>
  action$
    .ofType(GET_AVATAR)
    .mergeMap(action =>
      ajax({
        url: 'https://graph.microsoft.com/v1.0/me/photo/$value',
        headers: {
          'Authorization': 'Bearer ' + myToken
        },
        responseType: 'arraybuffer'
      })
      .do(res => console.log(res))  // <- the result
      .map(getAvatarSucceed)
      .catch(getAvatarFailed)
    );

Since this question actually is unrelated to redux-observable, here's a working example demonstrating getting the binary data and then creating an <img> with it: 由于这个问题实际上与redux-observable无关,这里有一个工作示例,演示获取二进制数据然后用它创建<img>

https://jsbin.com/mimijot/edit?js,output https://jsbin.com/mimijot/edit?js,output

import { ajax } from 'rxjs/observable/dom/ajax';

ajax({
  url: 'https://proxy.apisandbox.msdn.microsoft.com/svc?url=https%3A%2F%2Fgraph.microsoft.com%2Fv1.0%2Fme%2Fphoto%2F%24value',
  headers: { 'Authorization': 'Bearer {token:https://graph.microsoft.com/}' },
  responseType: 'arraybuffer'
})
  .subscribe(res => {
    console.log(res);
    const buffer = res.response;
    const blob = new Blob([buffer], { type: 'image/jpeg' });
    const url = URL.createObjectURL(blob);
    const img = document.createElement('img');

    img.src = url;
    document.body.appendChild(img);
  });

When building the Graph explorer with Angular 4, I encountered the same issue. 使用Angular 4构建Graph explorer时,遇到了同样的问题。 In our case, when requesting images we have to set the responseType parameter to ArrayBuffer instead of the default value. 在我们的例子中,在请求图像时,我们必须将responseType参数设置为ArrayBuffer而不是默认值。

https://github.com/microsoftgraph/microsoft-graph-explorer/blob/master/src/app/graph-service.ts#L54 https://github.com/microsoftgraph/microsoft-graph-explorer/blob/master/src/app/graph-service.ts#L54

case "GET": // for all JSON requests to Graph
        return this.http.get(query, {headers: requestHeaders}).toPromise();
case "GET_BINARY": // when fetching images
        return this.http.get(query, {responseType: ResponseContentType.ArrayBuffer, headers : requestHeaders}).toPromise();

And then when processing the response, we get the blob URL and set the image element's src: 然后在处理响应时,我们获取blob URL并设置image元素的src:

 let blob = new Blob( [ result.arrayBuffer() ], { type: "image/jpeg" } );
 let imageUrl = window.URL.createObjectURL( blob );

 const imageResultViewer = <HTMLImageElement>document.getElementById("responseImg");
 imageResultViewer.src = imageUrl;

It looks like Rx.DOM.ajax has the responseType property, so I recommend changing that but I'm not an RxJS expert! 看起来Rx.DOM.ajax有responseType属性,所以我建议改变它,但我不是RxJS专家! More info about XMLHttpRequest.responseType can be found at https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/responseType 有关XMLHttpRequest.responseType更多信息, 访问https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/responseType

Final code: 最终代码:

export const getAvatarEpic = (action$, store) =>
action$
.ofType(GET_AVATAR)
.mergeMap(action =>
  aja:@{
    url: 'https://graph.microsoft.com/v1.0/me/photo/$value',
    responseType: 'arraybuffer',
    headers: {
      // 'Content-Type': 'image/jpeg',
      'Authorization': 'Bearer ' + store.getState().auth.token
    }
  })
    .map(getAvatarSucceed)
    .catch(getAvatarFailed)
); 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM