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

发布时间: 2021-01-30 14:23:02 作者: 大象笔记

例如,我想将 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 的相关参数:

arraybuffer 与 blob 的区别

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

Blob 对象表示一个二进制文件的数据内容,通常用来读写文件,比如一个图片文件的内容就可以通过 Blob 对象读写。 所以下载的 Excel 文件,就需要用 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 结果还靠谱。

参考

我是一名山东烟台的开发者,联系作者