VBA:通过 HTTPS 下载图片
Posted
技术标签:
【中文标题】VBA:通过 HTTPS 下载图片【英文标题】:VBA: Download a picture via HTTPS 【发布时间】:2020-10-08 17:16:00 【问题描述】:我正在尝试使用 VBA(MS Access 2016)从网站(Grafana 监控工具,API)下载图片。这是一个使用自签名证书的 HTTPS 地址,需要用户名和密码进行身份验证。
我目前正在使用以下代码下载图片:
Function DownloadFile(ByVal myURL As String, ByVal LocalFileName As String)
Dim WinHttpReq As Object
Set WinHttpReq = CreateObject("WinHttp.WinHttpRequest.5.1")
WinHttpReq.Option(4) = 13056 'Ignore SSL Errors
WinHttpReq.Open "GET", myURL, False
WinHttpReq.setRequestHeader "Accept", "*/*"
WinHttpReq.setRequestHeader "User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"
WinHttpReq.setRequestHeader "Proxy-Connection", "Keep-Alive"
WinHttpReq.Send
myURL = WinHttpReq.ResponseBody
If WinHttpReq.Status = 200 Then
Set oStream = CreateObject("ADODB.Stream")
oStream.Open
oStream.Type = 1
oStream.Write WinHttpReq.ResponseBody
oStream.SaveToFile LocalFileName, 2
oStream.Close
Else
MsgBox "Returncode:" & WinHttpReq.Status & " Unable to download picture."
End If
End function
如果我将 HTTPS-URL 粘贴到浏览器中,我会得到正确的图片。这张图片我想通过上面的代码下载为 PNG 文件。但我下载的不是图片,而是以下 html 代码:
<!DOCTYPE html>
<html lang="en">
<head>
<script>
!(function()
if ('PerformanceLongTaskTiming' in window)
var g = (window.__tti = e: [] );
g.o = new PerformanceObserver(function(l)
g.e = g.e.concat(l.getEntries());
);
g.o.observe( entryTypes: ['longtask'] );
)();
</script>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="viewport" content="width=device-width" />
<meta name="theme-color" content="#000" />
<title>Grafana</title>
<base href="/" />
<link
rel="preload"
href="public/fonts/roboto/RxZJdnzeo3R5zJw.woff2"
as="font"
crossorigin
/>
<link rel="icon" type="image/png" href="public/img/fav32.png" />
<link rel="apple-touch-icon" sizes="180x180" href="public/img/apple-touch-icon.png" />
<link rel="mask-icon" href="public/img/grafana_mask_icon.svg" color="#F05A28" />
<link rel="stylesheet" href="public/build/grafana.dark.4d0490af40c.css" />
<script>
performance.mark('css done blocking');
</script>
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
<meta name="msapplication-TileColor" content="#2b5797" />
<meta name="msapplication-config" content="public/img/browserconfig.xml" />
</head>
<body class="theme-dark app-grafana">
<style>
.preloader
height: 100%;
flex-direction: column;
display: flex;
justify-content: center;
align-items: center;
.preloader__enter
opacity: 0;
animation-name: preloader-fade-in;
animation-iteration-count: 1;
animation-duration: 0.9s;
animation-delay: 1.35s;
animation-fill-mode: forwards;
.preloader__bounce
text-align: center;
animation-name: preloader-bounce;
animation-duration: 0.9s;
animation-iteration-count: infinite;
.preloader__logo
display: inline-block;
animation-name: preloader-squash;
animation-duration: 0.9s;
animation-iteration-count: infinite;
width: 60px;
height: 60px;
background-repeat: no-repeat;
background-size: contain;
background-image: url("data:image/svg+xml,%3csvg version='1.1' id='Layer_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' width='351px' height='365px' viewBox='0 0 351 365' style='enable-background:new 0 0 351 365%3b' xml:space='preserve'%3e %3cstyle type='text/css'%3e .st0%7bfill:url(%23SVGID_1_)%3b%7d %3c/style%3e %3cg id='Layer_1_1_'%3e %3c/g%3e %3clinearGradient id='SVGID_1_' gradientUnits='userSpaceOnUse' x1='175.5' y1='445.4948' x2='175.5' y2='114.0346'%3e %3cstop offset='0' style='stop-color:%23FFF100'/%3e %3cstop offset='1' style='stop-color:%23F05A28'/%3e %3c/linearGradient%3e %3cpath class='st0' d='M342%2c161.2c-0.6-6.1-1.6-13.1-3.6-20.9c-2-7.7-5-16.2-9.4-25c-4.4-8.8-10.1-17.9-17.5-26.8 c-2.9-3.5-6.1-6.9-9.5-10.2c5.1-20.3-6.2-37.9-6.2-37.9c-19.5-1.2-31.9%2c6.1-36.5%...2c1.6%2c2.3%2c3%2c2.1c1.5-0.1%2c2.6-1.3%2c2.6-2.8C342.6%2c170.4%2c342.5%2c166.1%2c342%2c161.2z'/%3e %3c/svg%3e");
.preloader__text
margin-top: 16px;
font-weight: 500;
font-size: 14px;
font-family: Sans-serif;
opacity: 0;
animation-name: preloader-fade-in;
animation-duration: 0.9s;
animation-delay: 1.8s;
animation-fill-mode: forwards;
.preloader__text--fail
display: none;
.preloader--done .preloader__bounce,
.preloader--done .preloader__logo
animation-name: none;
display: none;
.preloader--done .preloader__logo,
.preloader--done .preloader__text
display: none;
color: #ff5705 !important;
font-size: 15px;
.preloader--done .preloader__text--fail
display: block;
[ng\:cloak],
[ng-cloak],
.ng-cloak
display: none !important;
</style>
<div class="preloader">
<div class="preloader__enter">
<div class="preloader__bounce">
<div class="preloader__logo"></div>
</div>
</div>
<div class="preloader__text">Loading Grafana</div>
<div class="preloader__text preloader__text--fail">
<p>
<strong>If you're seeing this Grafana has failed to load its application files</strong>
<br />
<br />
</p>
<p>
1. This could be caused by your reverse proxy settings.<br /><br />
2. If you host grafana under subpath make sure your grafana.ini root_url setting includes subpath<br />
<br />
3. If you have a local dev build make sure you build frontend using: yarn start, yarn start:hot, or yarn
build<br />
<br />
4. Sometimes restarting grafana-server can help<br />
</p>
</div>
</div>
<grafana-app class="grafana-app" ng-cloak>
<sidemenu class="sidemenu"></sidemenu>
<app-notifications-list class="page-alert-list"></app-notifications-list>
<dashboard-search></dashboard-search>
<div class="main-view">
<div ng-view class="scroll-canvas"></div>
</div>
</grafana-app>
<script>
window.grafanaBootData =
user: "isSignedIn":false,"id":0,"login":"","email":"","name":"","lightTheme":false,"orgCount":0,"orgId":0,"orgName":"","orgRole":"","isGrafanaAdmin":false,"gravatarUrl":"","timezone":"browser","locale":"en-US","helpFlags1":0,"hasEditPermissionInFolders":false,
settings: "alertingEnabled":true,"alertingErrorOrTimeout":"alerting","alertingMinInterval":1,"alertingNoDataOrNullValues":"no_data","allowOrgCreate":false,"appSubUrl":"","authProxyEnabled":false,"buildInfo":"buildstamp":1582200229,"commit":"3fa63cfc34","edition":"Open Source","env":"production","hasUpdate":false,"isEnterprise":false,"latestVersion":"","version":"6.6.2","datasources":"-- Dashboard --":"meta":"type":"datasource","name":"--...plugins","url":"/plugins"],"id":"help","text":"Help","subTitle":"Grafana v6.6.2 (3fa63cfc34)","icon":"gicon gicon-question","url":"#","sortWeight":-1200,"hideFromMenu":true]
;
window.onload = function()
var preloader = document.getElementsByClassName("preloader");
if (preloader.length)
preloader[0].className = "preloader preloader--done";
;
</script>
<script src="public/build/runtime.4d0490a94b199a11f40c.js" type="text/javascript"></script>
<script src="public/build/angular~app.4d0490a94b199a11f40c.js" type="text/javascript"></script>
<script src="public/build/app.4d0490a94b199a11f40c.js" type="text/javascript"></script>
<script src="public/build/moment~app.4d0490a94b199a11f40c.js" type="text/javascript"></script>
<script src="public/build/vendors~app.4d0490a94b199a11f40c.js" type="text/javascript"></script>
<script>
performance.mark('js done blocking');
</script>
有人知道我如何在 VBA 中解决这个问题吗?
【问题讨论】:
你真的被这个方法捆绑了吗?也许尝试 API 功能。请参阅***.com/questions/50296020/…中的 Gustav 回答 这能回答你的问题吗? Downloading Images from URL and Renaming 我已经研究了很多,发现 XMLHTTP 或 URLDownloadToFile 等其他方法不支持 HTTPS。请参阅codeproject.com/Tips/506439/Downloading-files-with-VBScript 我发现的唯一可以处理 HTTPS 的方法是 WinHttp.WinHttpRequest.5.1。 点评***.com/questions/22051960/… 感谢@June7 的推荐。我测试了来自***.com/questions/22051960/… 的代码,它最终遇到了同样的问题。该文件是 HTML 文档而不是 PNG。 【参考方案1】:我找到了解决方案:我是 Grafana 的身份验证问题。下面的代码解决了这个问题:
Function DownloadFile(ByVal myURL As String, ByVal LocalFileName As String)
Dim WinHttpReq As Object
Set WinHttpReq = CreateObject("WinHttp.WinHttpRequest.5.1")
WinHttpReq.Option(4) = 13056 'Ignore SSL Errors
WinHttpReq.Open "GET", myURL, False
WinHttpReq.setRequestHeader "Accept", "*/*"
WinHttpReq.setRequestHeader "User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"
WinHttpReq.setRequestHeader "Proxy-Connection", "Keep-Alive"
WinHttpReq.setRequestHeader "Authorization", "Bearer xxxxxxxxxxxxxxxAPI_keyxxxxxxxxxxxx"
WinHttpReq.Send
myURL = WinHttpReq.ResponseBody
If WinHttpReq.Status = 200 Then
Set oStream = CreateObject("ADODB.Stream")
oStream.Open
oStream.Type = 1
oStream.Write WinHttpReq.ResponseBody
oStream.SaveToFile LocalFileName, 2
oStream.Close
Else
MsgBox "Returncode:" & WinHttpReq.Status & " Unable to download picture."
End If
End function
【讨论】:
以上是关于VBA:通过 HTTPS 下载图片的主要内容,如果未能解决你的问题,请参考以下文章
VBA WinHTTP 从受密码保护的 https 网站下载文件
使用 VBA 插入图片,Excel 2010 和 Excel 2016 之间的大小不同