前言: 前端时间在 B 站看到了一个 UP 主做的基于二维码的文件传输工具的水平,我感觉蛮有意思的。他展示的效果是一个显示器不断闪动二维码,另一个是手机在扫码读取,最后把结果汇总起来。这种方式的安全性很高,可以用于两个隔离网络的设备之间互相传输文件,不过速度肯定很慢了,用来传输一些小的,重要的文件是再合适不过了。不过,这中间的过程真的是蛮有趣的,只要你可以看到,那就说明信息已经有了,只是你可能没有能力去获取它。推荐大家去看看金观涛的这本书,对人认识世界的方式有很大的启发作用。
人们只有对外部世界有所认识,才可以能动地去改造它。 反之,人们只有参与对外部世界的改造,才能够获得它他们的真知。《控制论和科学方法论》· 金观涛
所以,受到这个启发,我也打算做一个基于二维码的文件传输工具。我当时的设想是:把一个文件分成 n 份,每一份带上一个编号,然后生成 n 个二维码,另一个设备获取这些二维码,然后解码,根据编号把文件整合还原。不过,我只是想了想,后来也没有去做,哈哈哈。这样做原理上是行得通的,不过最后那步需要很多的处理逻辑,这块不是我了解的,我就没做了。不过,最近又想到了另一个点子,就是这篇博文要聊的,在命令行查看图片。有很多工具可以做到这一点,通常是安装一个库直接在命令行显示或者是通过网络的方式(例如: python -m http.server 9000),通过网络把图片传输出去展示。
这里我想着结合二维码来玩一玩,不过我得先声明一下,我这样做很麻烦,而且感觉没啥用处。我这里想说的是在基于远程连接 Linux 的情况下,通过命令行查看图片的方法,不过我整个过程都是在 Windows 上操作的,但是我希望你可以理解。
这里只是一个简单的想法,所以我们就直接开始吧。Let’s Go!
安装 python 库:pip install pillow qr
注:我想你应该分得清,你该用 pip 还是 pip3。
pillow
这个库是一个大名鼎鼎的图像处理库,不过我基本没有用过,但是我听过,所以我就选择了它。因为没有什么比安装一个库更方便的了。这个库是涉及图像处理的,我平时也接触不到,所以我这里直接把官方文档中我用的那部分贴出来了,这里我只是用它来生成缩略图。
注:thumbnail
就是缩略图的英文,你应该认识的。
然后这里是我生成的测试图片,这张大图是原图,我的电脑壁纸。它有 1.56 MB,对于一个二维码来说太大了。其实二维码的容量是很小的,很难塞得下一张图片的,所以首先要做的就是把它变小,因为这里只是查看一下图片,并不需要原图。然后我进行了测试,最终选择了 25*25 这个尺寸的,它的大小总体来说合适,再小的话,就很难看清图片的轮廓了。
qr 就是二维码的英文,或者叫 QR Code
。它的使用就是很简单了,最简单的直接就是根据输入的内容生成一个二维码,也可以把二维码保存在文件中,不过这里它最重要的就是在命令行显示了,如果用它生成图片的话,那样就回到了开头了。
图片转 Base64
这里我只是想要做一个简单的验证,就不用代码的方式来处理了,GUI 是很方便的。而且 Windows 并没有 Linux 的 base64
命令行,所以我就用网页编码代替了,不过我也发现一个好处,因为它生成的是网页可以直接看的格式,所以调试起来蛮方便的,而且只是在前面加了固定的头部字段,也是可以接受的。
这样生成的 base64 字符串,直接在浏览器的地址栏输入是可以打开的。所以如果有时候你得到了一个 base64 字符串,你想要快速查看它的话,可以这样做。
Base64 进行 URLEncode
我会把生成的 base64 字符串当作一个参数来传递,所以需要对它进行 URL 编码,这里也是用一个在线工具来处理了。
如果直接生成图片的话,二维码扫描得到的只是一个字符串,这样还是很麻烦。尽管你可以直接在浏览器地址栏输入这串图片的 base64,但是我没有找到方法可以在扫码后这样做。因为经常浏览网页,很多时候需要跳转到外部链接,我以为可以通过将外部链接设置为这个 base64 字符串来达到目的。但是我进行尝试才发现,我对于这种跳转的理解是不对的(我以前以为它是在新页面打开这个链接,但是看起来并不是这样做的),所以这样也是不行的。
所以,此路不通,那就没有办法了,只能自己来做最后这一步了。因为我已经得到了图片的 base64,所以很容易就可以得到图片的,因为没有合适的 公开的方法,所以就只能自己写一个简单的接口来测试了。
package main
import (
"encoding/base64"
"fmt"
"log"
"strings"
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
r.GET("/test", func(ctx *gin.Context) {
img := ctx.Query("img") // data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2
b64Str := img[strings.LastIndex(img, ",")+1:] // 因为base64不包括逗号,所以定位最后一个逗号就行了
data, err := base64.StdEncoding.DecodeString(b64Str) // base64 也有好几种分类呢
if err != nil {
log.Fatal(err)
}
ctx.Data(200, "image/jpeg", data)
})
r.Run(":8080")
}
所以,尝试在浏览器访问该链接:http:/127.0.0.1:8080/test?img={base64}
这一步也搞定了,那么就把这个链接变成塞进二维码就行了。我一开始用了网上公开的免费二维码网站,我才发现它们支持的字数很少,大概300个左右,那对于我来说也还是太小了(内容太多,会导致生成的二维码复杂,扫码成功率也会降低的)。不过,幸好我用的是 qr 这个命令行,不过二维码太大了,也会导致一页无法展示完全。
注:这里我改成了局域网地址,因为用手机扫描的话,需要和电脑处于同一网络下(我的这个测试接口在我的电脑上运行,同时上面的运行参数只填写了端口,这样就可以接收所有主机的流量了,电脑会提示一个警告的,同意即可。)
直接生成文件是没有问题的,如果直接在命令行展示的话内容就错乱了,这样根本无法进行扫描操作了。这时候只能用非常之法了,把命令行程序全屏展示,不过只是勉强放得下,可以进行扫描操作。那还能做的那就是改字体,把字体改小,我发现这样才是最合适的,也不会影响到手机扫码,不过想看清文字那就困难了。
然后就可以使用手机扫描测试了,这里我用微信扫一扫:
最开始的时候,我的想法是把图片完全展示,不过受限制于这中间传输的限制,还是挺困难的。所以,我就退而求其次,只把图片的部分信息拿出来,这里面的关键点是没有通过网络进行传输信息(获取图片信息的时候),不过若要是想完全传输一整个图片或者小文件,那也需要很多张二维码才行了,总之还是很麻烦的。
注意:如果只是为了传输文件,这里的base64转换是不必要的,并且转换后它会增加30%的大小。我使用它是因为我需要它作为后面展示时的http参数。