tampermonkey 上传 Blob 文件到其他服务器,application/octet-stream 版

文章目录

    例如,我想将 https://www.sunzhongwei.com 网页中下载到的 Excel 文件,上传到其他服务器。这里以 http://localhost:5000 为本地测试环境。

    tampermonkey 中是否可以使用 fetch / jQuery ajax

    还是必须使用 GM_xmlhttpRequest ?

    测试了一下,用 fetch 确实不行,必须使用 GM_xmlhttpRequest 。

    以下是使用 fetch 的报错信息,估计使用 jquery ajax 也是同样的结果。

    Access to fetch at 'http://localhost:5000/' from origin 'https://www.sunzhongwei.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
    
    POST http://localhost:5000/ net::ERR_FAILED
    
    Uncaught (in promise) TypeError: Failed to fetch
    

    如果是同一个域名,就可以使用 fetch 了。

    官方文档对 GM_xmlhttpRequest 的说明

    https://wiki.greasespot.net/GM.xmlHttpRequest

    This method performs a similar function to the standard XMLHttpRequest object, but allows these requests to cross the same origin policy boundaries.

    也就是说使用这个函数才能绕过 cross the same origin policy 的限制。

    URL is not a part of the @connect list

    在向本地服务 http://localhost:5000 提交数据时,报错:

    URL is not a part of the @connect list

    看起来是没有添加域名白名单。注意,不需要加端口号,如果加了端口号,同样会报这个错误。

    正确的设置如下:

    // @connect localhost
    

    指定 Excel 文件的下载格式

    GM_xmlhttpRequest 的相关参数:

    • 请求参数 responseType: one of arraybuffer, blob, json
    • 返回值 response: the response data as object if details.responseType was set

    arraybuffer 与 blob 的区别

    Blob,是英文 Binary Large Object (二进制大型对象)的缩写。

    Blob 对象表示一个二进制文件的数据内容,通常用来读写文件,比如一个图片文件的内容就可以通过 Blob 对象读写。
    所以下载的 Excel 文件,就需要用 Blob 格式来存储。到上传的时候,再原封不动地传到新的服务器上。

    与 ArrayBuffer 区别:

    • Blob 用于操作二进制文件
    • ArrayBuffer 用于操作内存。没太看懂,感觉是以数组的形式打印二进制流。

    Blob 上传

    GM_xmlhttpRequest 的 binary 参数,支持数据二进制模式。

    binary send the data string in binary mode

    参考:

    https://www.tampermonkey.net/documentation.php#GM_getResourceText

    这里的 binary 是用来设置参数 data 的类型,所以只能设置为 true / false。

    可行的 js 代码

    GM_xmlhttpRequest ( {
      method:     "POST",
      url:        "https://www.sunzhongwei.com/some-excel",
      data:       data,
      responseType: "blob",		// 获取 response 为 blob 类型
      headers:    {
        "Content-Type": "application/x-www-form-urlencoded"
      },
      onload:     function (response) {
    	console.log ("got response");
    	GM_xmlhttpRequest ( {
    		method:     "POST",
    		url:        "http://localhost:5000",
    		data:       response.response,
    		binary:     true,		// 设置 data 以二进制形式上传
    		headers:    {},
    		onload:     function (response) {
    			console.log (response.responseText);
    		}
    	});
      }
    });
    

    Python 如何获取传递来的二进制数据

    以 flask 为例:

    # env FLASK_APP=server.py flask run
    
    from flask import Flask, escape, request
    
    app = Flask(__name__)
    
    
    @app.route('/', methods=['GET', 'POST'])
    def hello():
        data = request.get_data()
    
        with open("/mnt/d/test_a.xls", "wb") as f:
            f.write(data)
    
        return "OK"
    

    打开文件,果然是原始的 Excel。测试成功。

    Java 如何获取传递来的二进制数据

    参考 tampermonkey 上传 Blob 文件到其他服务器,multipart/form-data 版 里的实现。

    感悟

    读官方文档,很多时候就能理出实现思路,比 Google 结果还靠谱。

    参考

    • https://stackoverflow.com/questions/19393744/use-gm-xmlhttprequest-to-post-data-on-chrome

    关于作者 🌱

    我是来自山东烟台的一名开发者,有感兴趣的话题,或者软件开发需求,欢迎加微信 zhongwei 聊聊,或者关注我的个人公众号“大象工具”, 查看更多联系方式