版权声明:本文为博主原创文章,未经博主允许不得转载。转载请标明文章出处和原文链接。欢迎加QQ群交流:191695206 https://blog.csdn.net/wangzl1163/article/details/82800538
前端访问下载图片API下载图片。
一、ASP.NET Core Web API代码
方案一:
[Route("api/[controller]")]
[ApiController]
public class DownloadController : BaseController
{
// GET: api/Download
[HttpGet]
public FileStreamResult Get()
{
//方案一 方法返回值:IActionResult,FileResult,FileStreamResult
FileStream fileStream = new FileStream(Directory.GetCurrentDirectory() + Common.ConfigManager.GetConfigValue("createrFilesPath") + Common.ConfigManager.GetConfigValue("fileName"), FileMode.Open, FileAccess.Read);
return File(fileStream, "application/octet-stream", Common.ConfigManager.GetConfigValue("fileName"));
}
}
注:方法返回值类型可以为IActionResult,FileResult,FileStreamResult中的任意一种。
方案二:
[Route("api/[controller]")]
[ApiController]
public class DownloadController : BaseController
{
// GET: api/Download
[HttpGet]
public void Get()
{
//方案二,方法无返回值,void,当用户点击下载对话窗上的下载按钮后会再次请求
Response.ContentType = "application/octet-stream";
Response.ContentType = "image/jpeg";
//通知浏览器下载文件而不是打开
Response.Headers.Add("Content-Disposition", "attachment; filename=" + Common.ConfigManager.GetConfigValue("fileName"));
Response.SendFileAsync(Directory.GetCurrentDirectory() + Common.ConfigManager.GetConfigValue("createrFilesPath") + Common.ConfigManager.GetConfigValue("fileName"));
}
}
注:该方案方法不需要返回值类型。需要注意的一点是:浏览器弹出下载对话框后当用户点击下载按钮后浏览器会再次请求接口。
方案三:
[Route("api/[controller]")]
[ApiController]
public class DownloadController : BaseController
{
// GET: api/Download
[HttpGet]
public FileStreamResult Get()
{
//方案三
var addrUrl = Directory.GetCurrentDirectory() + Common.ConfigManager.GetConfigValue("createrFilesPath") + Common.ConfigManager.GetConfigValue("fileName");
var stream = System.IO.File.OpenRead(addrUrl);
string fileExt = ".jpg"; // 这里可以写一个获取文件扩展名的方法,获取扩展名
//获取文件的ContentType
var provider = new Microsoft.AspNetCore.StaticFiles.FileExtensionContentTypeProvider();
var memi = provider.Mappings[fileExt];
var fileName = Path.GetFileName(addrUrl);
//在header中设置filename以便前端取用
Response.Headers.Add("fileName", fileName);
//支持跨域时可以通过axios等http库获取到在header中的数据
Response.Headers.Add("Access-Control-Expose-Headers", "fileName");
return File(stream, memi, fileName);
}
}
注:方案三可以看做方案一的优化,避免了方案一的大量硬编码
说明:这次实现三个方案中的图片地址均为固定的一张图片的地址,采用了物理地址,实际项目中图片地址可以是物理地址也可以是虚拟地址(网络地址)。
二、前端代码
a、在页面简单实现,如下
扫描二维码关注公众号,回复:
3920965 查看本文章
// window.location.href = 'http://localhost:5000/api/Download'
window.open('http://localhost:5000/api/Download')
b、封装在axios中的get方法中。页面使用Vue.js实现。如下
// 封装的axios方法
import http from '../config/axios/index'
export function DownloadQRCode () {
return new Promise((resolve, reject) => {
// window.location.href window.open 放在Promise中也是没有问题的。
// window.location.href = 'http://localhost:5000/api/Download'
// window.open(' http://localhost:5000/api/Download')
http
.get('/Download', {
responseType: 'blob' // stream也可以,但是浏览器会报属性无法识别的警告,arraybuffer也可以
})
.then((res) => {
return resolve(res)
})
})
}
// Vue.js中的代码实现
import { DownloadQRCode } from '../../apis/WXAQRCode'
// 此处省略部分代码
downloadImg () {
if (this.isSuccess) {
DownloadQRCode().then(res => {
console.log('下载', res)
// 这里res.data是返回的 blob 对象
var blob = new Blob([res.data], { type: 'application/' + res.headers['content-type'] })
var downloadElement = document.createElement('a')
var href = window.URL.createObjectURL(blob) // 创建下载的链接
downloadElement.href = href
downloadElement.download = res.headers.filename // 下载后文件名
// 此写法兼容可火狐浏览器
document.body.appendChild(downloadElement)
downloadElement.click() // 点击下载
document.body.removeChild(downloadElement) // 下载完成移除元素
window.URL.revokeObjectURL(href) // 释放掉 blob 对象
})
} else {
this.$Message.error('请先生成二维码')
}
}
注:前端的实现是采用了触发点击事件,在点击事件中访问下载图片接口的做法。location.href和window.open方式都是可以的。
三、总结
这三种方案中接口返回的都是文件流,也就是说web应用程序打开并读取文件,然后以流(字节序列)为结果进行返回了,浏览器接收到的是文件流。