代码之家  ›  专栏  ›  技术社区  ›  Hongbo Miao

如何使用redux observable正确获取二值图像?

  •  1
  • Hongbo Miao  · 技术社区  · 7 年前

    我正在尝试使用redux observable获取图像。

    基于 Microsoft Graph API ,它返回所请求照片的二进制数据。

    我使用Postman成功地获得了图像(由于它是二进制的,所以在结果中显示了图像)。

    redux-observable , 我得到的总是 null 响应类型 总是 json 无论我付出什么 喜欢 image/jpeg , text/plain application/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)
        );
    

    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
    }
    
    2 回复  |  直到 7 年前
        1
  •  3
  •   jayphelps    7 年前

    首先,我想确定redux observable和RxJ是分开的。这个问题实际上是一个RxJS问题,因为redux observable很小,实际上几乎所有问题都服从于惯用Rx,所以几乎所有问题都是这样(即使在使用redux observable时也是如此)。这一点很重要,因为当你提出问题时,如果你只是把它们当作Rx问题,你会发现更多的帮助和资源,因为这是一个更大的整体社区。希望这有帮助!


    如果您使用RxJS v5的内置ajax实用程序,则需要使用常规的 ajax() 助手,不是速记员 ajax.get()

    然后你可以提供 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)
        );
    

    由于这个问题实际上与redux observable无关,下面是一个工作示例,演示如何获取二进制数据,然后创建一个 <img> 有了它:

    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);
      });
    
        2
  •  1
  •   David    7 年前

    responseType ArrayBuffer 而不是默认值。

    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();
    

    然后在处理响应时,我们得到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;
    

    Rx.DOM.ajax 具有responseType属性,因此我建议更改它,但我不是RxJS专家!有关的更多信息 XMLHttpRequest.responseType 可在找到 https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/responseType

    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)
    );