【问题标题】:How can I use Axios to display images or videos using html img/video tag?如何使用 Axios 使用 html img/video 标签显示图像或视频?
【发布时间】:2020-09-06 12:06:43
【问题描述】:

我正在使用 axios 和 asp.net core 3.1 为后端 api 开发一个反应应用程序(打字稿模板)。而且,例如,我有这个受保护的(使用 JWT 的身份)端点来从服务器获取图像文件为FileStream

[Authorize(Policy = AspianCorePolicy.AdminAttachmentGetImagePolicy)]
[HttpGet("images/{filename}")]
public async Task<ActionResult> GetImage(string filename)
{
     var imageDto = await Mediator.Send(new GetImage.Query { FileName = filename });
     return File(imageDto.Memory, imageDto.MimeType, imageDto.FileName);
}

考虑到这一点,我还有一些大型视频文件要流式传输。

  • 话虽如此,如果我想使用 Axios 将其作为文件流获取并显示在imgvideo 标签甚至下载文件,如何通过axios和html标签做到这一点?我应该使用 Axios responseType: 'stream' 吗?如果是这样,我该怎么做?

【问题讨论】:

  • 您是否想过在服务器端代码中将图像转换为 base64 字符串并在 img 标签中使用它而不是静态文件?例如
  • 其实是的。但是无论您在服务器端做什么,您都必须以 Axios Promise 或其他形式接收结果,因此,您将遇到身份验证问题,并且所有内容加上接收 Promise 结果都有其自身的复杂性.我最近一直在考虑使用直接 url 到端点,然后在服务器端检查我的刷新令牌 httponly cookie 以查看用户是否经过身份验证。
  • 为什么不直接将你的 api url 分配给 img/video 标签?
  • @Evk 正如我在问题中所说,因为端点受到保护并且我希望它受到保护所以要获得结果我必须经过身份验证,因此我必须每次都在请求标头之间发送 JWT我发送一个 http 请求以获取图像作为示例,并且我不能使用 img 标签或“a”标签来做到这一点,因为它们不接受要发送的标头。
  • 所以我猜想将响应类型设置为“blob”,然后使用 createObjectURL(response.data)?

标签: c# reactjs typescript asp.net-core axios


【解决方案1】:

axios api 是直截了当的。你可以在这里找到axios browser examples

显示图像或视频会非常相似。

设置调用以从 Web api 检索 blob 响应。

var config = { responseType: 'blob' }

然后进行调用并从 blob 创建一个数据 url。然后可以在目标元素上设置数据 url:

图片

axios.get("api/media?fileName=TestImage.png", config)
    .then(resp => {
        $("#img1").attr("src", window.URL.createObjectURL(resp.data));
    });

视频

axios.get("api/media?fileName=TestVideo.mp4", config)
    .then(resp => {
        $("#video1").attr("src", window.URL.createObjectURL(resp.data));
    });

下载将归档一个类似的过程,除了您在下载属性设置为 true 的 html 锚元素上设置 href。这可以通过编程方式在创建后单击链接(受此gist 启发)

图片

axios.get("api/media?fileName=TestImage.png", config)
    .then(resp => {
        download(resp);
    });

视频

axios.get("api/media?fileName=TestVideo.mp4", config)
    .then(resp => {
        download(resp);
    });

还有下载功能

function download(resp) {
    var url = urlCreator.createObjectURL(resp.data);
    var fileName = resp.headers["content-disposition"].split("filename=")[1].split(";")[0];
    var link = document.createElement('a');
    $(link).attr("href", url).attr("download", fileName);
    link.click();
    window.URL.revokeObjectURL(url);
}

responseType: 'stream' 而言,我无法让它在浏览器中运行。根据 Axios Github,streaming is currently not supported in browsers 由于使用了 XHR 请求。

将所有这些放在一起,在您指定的路线上使用一个有效的 Web api 端点,这将是有效的代码示例。

$(document).ready(() => bindHandlers());
var urlCreator;

function bindHandlers() {
  urlCreator = window.URL || window.webkitURL;

  $("#btnShowImage").click(() => btnShowImageClick());
  $("#btnShowVideo").click(() => btnShowVideoClick());
  $("#btnDownloadImage").click(() => btnDownloadImageClick());
  $("#btnDownloadVideo").click(() => btnDownloadVideoClick());
  $("img1").hide();
  $('#videoWrapper').hide();
}
var config = {
  responseType: 'blob'
}

function btnShowImageClick() {
  axios.get("api/media?fileName=TestImage.png", config)
    .then(resp => {
      $("#img1").attr("src", urlCreator.createObjectURL(resp.data));
      $("#img1").show();
      $('#videoWrapper').hide();
    });
}

function btnShowVideoClick() {
  axios.get("api/media?fileName=TestVideo.mp4", config)
    .then(resp => {
      $("#img1").hide();
      $("#video1").attr("src", urlCreator.createObjectURL(resp.data))
      $('#videoWrapper').show();
    });
}

function btnDownloadImageClick() {
  axios.get("api/media?fileName=TestImage.png", config)
    .then(resp => {
      download(resp);
    });
}

function btnDownloadVideoClick() {
  axios.get("api/media?fileName=TestVideo.wmv", config)
    .then(resp => {
      download(resp);
    });
}

function download(resp) {
  var url = urlCreator.createObjectURL(resp.data);
  var fileName = resp.headers["content-disposition"]
    .split("filename=")[1].split(";")[0];
  var link = document.createElement('a');
  $(link).attr("href", url).attr("download", fileName);
  link.click();
  window.URL.revokeObjectURL(url);
}
<script src="https://cdn.jsdelivr.net/npm/axios@0.21.0/dist/axios.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="text-center">
  <h1 class="display-4">Axios Example</h1>
  <input id="btnShowImage" value="Show Image" type="button" />
  <input id="btnShowVideo" value="Show Video" type="button" />
  <input id="btnDownloadImage" value="Download Image" type="button" />
  <input id="btnDownloadVideo" value="Download Video" type="button" />
  <img id="img1" />
  <div id="videoWrapper">
    <video id="video1" controls="controls"></video>
  </div>
</div>

【讨论】:

  • 非常感谢您的彻底解决方案和您宝贵的时间 Alexander。实际上我的问题是我无法让 responseType: 'stream' 在浏览器中工作,所以我认为我做错了什么,然后我在这里问了这个问题。那么,即使我对大型视频文件也使用 blob,不会有问题吗?另一个问题是,每次我请求视频文件时,我是否必须等待文件完全接收,然后才能播放视频,或者它将在视频流等范围内接收,同时我可以播放它?
  • 我检查了 Udemy 的教程的预览视频链接,它们也是 blob,每个教程的链接都显示为模态。因此,如果我们假设我有一个带有 10 个“a”标签的 Modal,其中包含“href=blob ...”,那么页面或 Modal 会不会因为等待 Axios 响应接收到它们中的每一个而缓慢加载?
  • 从技术上讲,BlobURL 将引用已加载到浏览器内存中的 Blob 或文件,因此使用它们不会有延迟。尽管出于实际目的,但数据需要在创建之前完成下载。奇怪的是,您一开始不会将 10 个大型视频加载到 blob 中。您将为他们显示缩略图,并将视频单独放在页面上。您将遇到浏览器和服务器端内存限制,将非常大的 blob 加载到内存中。
猜你喜欢
  • 1970-01-01
  • 2019-03-29
  • 2023-03-20
  • 2014-09-29
  • 2017-09-10
  • 1970-01-01
  • 1970-01-01
  • 2015-09-20
相关资源
最近更新 更多