如何在浏览器中通过POST请求加载外文图片

How to load foreign image via POST request in browser?

本文关键字:请求 POST 加载 文图片 浏览器      更新时间:2023-09-26

我的web应用程序(HTML5 + JavaScript)需要显示由外部web服务生成的PNG图像。

然而,该web服务只支持POST请求。(更确切地说,它确实提供GET请求,但我必须传输大参数,因为GET URL变得太长了。)

此外,web服务与web应用程序具有不同的域,并且不提供适当的CORS标头,因此Ajax (XMLHTTPRequest)不起作用。

我的web应用程序是否仍然可以通过POST请求加载和显示外国图像?

我要求的解决方案是不同于以下讨厌的变通方法,这是我已经知道的:

  • 而不设置翻译请求的本地代理(也绕过同源策略)
  • 而不使用一些陌生人的远程代理
  • 不使用Java小程序
  • 不使用操作系统特定的功能,如ActiveX控件

但是,不能与Internet Explorer一起工作的解决方案是可以接受的。即使是Firefox或Chrome的特定解决方案也是值得赞赏的。

可怕的黑客:

向iframe提交表单,并在iframe中显示图像。

(但不要这样做,这听起来就像web服务器是为了避免图像直接嵌入到其他站点而设计的)

我有一些可能的解决方案…

解决方案1

如果您的图像小于25kb,您可以通过YQL执行以下操作:select * from data.uri where url="http://jquery.com/jquery-wp-content/themes/jquery/images/logo-jquery@2x.png"因此,您可以抓取base64图像并继续。要通过YQL执行POST,您应该添加类似and postdata="foo=foo&bar=bar"的东西,请查看本文。

警告:此方法的性能可能不是很好。从最终用户到YQL再到服务,然后再返回,会有相当多的延迟。也有一些服务器端处理YQL做base64编码的图像和提供一些JSON响应。

解决方案2

启用CORS或通过其他代理。一旦你这样做了,如果你仍然不能得到base64数据,那么你需要做两件事。首先添加一个处理二进制文件的jQuery传输。第二步处理二进制blob并将其转换为base64。

这是我找到的jQuery二进制传输

$.ajaxTransport("+binary", function(options, originalOptions, jqXHR){
   // check for conditions and support for blob / arraybuffer response type
    if (window.FormData && ((options.dataType && (options.dataType == 'binary')) || (options.data && ((window.ArrayBuffer && options.data instanceof ArrayBuffer) || (window.Blob && options.data instanceof Blob)))))
    {
        return {
            // create new XMLHttpRequest
            send: function(headers, callback){
        // setup all variables
                var xhr = new XMLHttpRequest(),
        url = options.url,
        type = options.type,
        async = options.async || true,
        // blob or arraybuffer. Default is blob
        dataType = options.responseType || "blob",
        data = options.data || null,
        username = options.username || null,
        password = options.password || null;
                xhr.addEventListener('load', function(){
            var data = {};
            data[options.dataType] = xhr.response;
            // make callback and send data
            callback(xhr.status, xhr.statusText, data, xhr.getAllResponseHeaders());
                });
                xhr.open(type, url, async, username, password);
        // setup custom headers
        for (var i in headers ) {
            xhr.setRequestHeader(i, headers[i] );
        }
                xhr.responseType = dataType;
                xhr.send(data);
            },
            abort: function(){
                jqXHR.abort();
            }
        };
    }
});

一旦你添加了传输,你就可以发出任何类型的AJAX请求。

$.ajax({
    type: "POST",
    url: 'http://myservice.com/service/v1/somethingsomething',
    dataType: 'binary',
    success: function(imgData) {
        var img = new Image(),
            reader = new window.FileReader();
        reader.readAsDataURL(imgData); 
        reader.onloadend = function() {
            img.src = reader.result
            $('#logo-events').append(img);
        }
    }
});

读卡器应该取Blob,输出base64版本。当读者完成转换/阅读时,它将创建一个图像并将其附加到某个地方。GET或POST不再重要。

我发现了这个相关的问题:Post data to JsonP

我认为它可能适用于你的情况。

基本上,向服务器发送json请求(同源策略不应该是问题),并加载响应和<img>

和@Quentin的回答一样,这个hack使用了一个(隐藏的)Iframe