2024年踩坑日志
1. 服务器时间问题
后端需要调用第三方接口,第三方接口又有5秒钟时间差的限制,在本地环境不会有问题,但是部署到云服务器上就会请求出错。因为云服务器的系统时间和真正的本地时间是有差距的,这个差距不是一两秒,而是一两分钟,导致请求出错,但是云服务器的硬件时间
又是准确的。
所以最后的解决方式是在云服务器里设定个定时任务
,定时将系统时间与硬件时间同步
。
2. 公众号文章问题
原本客户想要在小程序上展示公众号文章,后面小程序链接公众号成功后,发现拿不到那么多文章。
后面了解到是微信小程序那边没有对应的接口,因为公众号的文章是分为群发
与发布
两个类型。
如果文章是群发类型,就拿不到对应的公众号文章数据,因为微信没有提供群发类型文章接口,只提供了发布类型的文章接口,而因为群发类型会自动通知到关注公众号的用户,所以一般发布者都会设定成群发类型,导致拿不到数据。(纯微信的问题,一直没接口)
最后只能取消这个需求,除非是客户愿意将群发文章都重新写一遍变成发布类型文章。
3. 微信公众号文章在小程序展示
如果一个微信公众号文章想要在小程序中展示,需要与小程序进行绑定关联,这样才能在小程序的web-view
组件里展示文章内容。
不然就会出现无法打开该页面
和 无法打开该图文信息
的错误提示。
可以使用反向代理
的方式,中间加一层代理,将公众号文章的内容转发到小程序里。
但是这个代理需要有中间的服务器或者nginx来做,而且如果公众号文章里有图片的话,因为微信对公众号文章里的图片做了防盗链
,所以展示不出来。
因为web-view组件的限制,所以只能展示文字内容,也无法拿到文章的html结构,无法改里面图片元素的地址。
目前用nginx做反向代理的话,是无法解决这个防盗链问题。也许用后端接口的方式可以解决这个问题,但是实现起来会比较麻烦,所以暂时没有尝试。
4. 上传文件post请求报400
如果不是用ui库自带的upload组件里的action方式上传文件,而是采用自己post请求方式,会出现400错误。
明明在请求头已经"Content-Type": "multipart/form-data",但还是报错。
fetch('/api/upload', {
method: 'POST',
body: fd,
headers: {
'Content-Type': 'multipart/form-data'
}
})
而这个解决方法就是移除"Content-Type": "multipart/form-data"
。
使用post 请求上传文件的时候是不需要自己设置 Content-Type,会自动给你添加一个 boundary ,用来分割消息主体中的每个字段,如果这个时候自己设置了 Content-Type, 服务器就不知道怎么分割各个字段,因此就会报错。
5. 前端播放视频问题
前端video标签使用后端接口请求视频时,有些MP4视频会出现一直请求失败的情况,是因为默认浏览器是识别H264编码格式
的MP4视频,但是如果后端给的是H265编码格式
的MP4视频,前端就无法识别,导致一直请求,一直失败的情况。
要么就前端上传视频做个限制,使用mp4box.js查看上传文件的编码格式是否为H264;要么就后端进行处理,将上传的所有视频统一采用FFmpeg进行转码成H264的mp4视频,但是这样很吃后端服务器的性能,而且不同服务器视频转码的时间也不同,所以我这边采用的是前者限制上传文件的方式。
const checkMp4Mime = async (file) => {
return await new Promise((resolve) => {
if (file.type == "video/mp4") {
const reader = new FileReader();
const buffer = reader.readAsArrayBuffer(file);
reader.onload = async function (e) {
let arrayBuffer = e.target.result;
arrayBuffer.fileStart = 0;
const mp4boxfile = MP4Box.createFile();
mp4boxfile.onReady = (info) => {
const mime = info.mime;
const codec = mime.split("; ");
let res = false;
codec.forEach((item) => {
if (item.indexOf('codecs="') > -1 && item.indexOf('avc') > -1) res = true;
});
if (res) {
resolve(true);
} else {
resolve(false);
window.$notification.warning({
message: "只能上传编码格式为H264的MP4视频",
description: "浏览器播放mp4视频只支持H264编码格式",
duration: 5,
});
}
};
mp4boxfile.appendBuffer(arrayBuffer);
};
} else resolve(true);
});
};
6. 后端视频文件接口
如果是直接使用IO流去传输视频文件,那么前端得等整个视频文件下载完成才会去播放,当视频很大的时候,就需要等待很长的时间才能播放起来,而且对服务器的带宽压力也很大。
所以后端需要采用静态资源请求处理器ResourceHttpRequestHandler
。
实现代码在功能实现--静态资源请求处理器
中
7. pkg打包nodejs程序为exe文件会出现的问题
打包时会出现报错,这些太多就不说。在打包完exe文件后,在运行过程中,会突然卡死,但是按enter
能够继续接着之前的程序运行。
是因为CMD的属性设置为Quick Edit Mode和Insert Mode,当“不小心”鼠标点击页面,让CMD认为需要等待输入,则会陷入“卡死”,按下Enter让CMD任务输入完成继续输出显示程序的运行结果。
取消勾选Quick Edit Mode
和Insert Mode
这两项,解决这个问题
8. 前端项目打包后注意事项
前端项目一般来说打包后会出现dist文件夹,里面就是整个项目打包压缩好后的三件套文件(html+css+js)。
但是不能直接双击打开index.html来展示前端,因为在开发环境中,资源文件的引用路径通常是相对于当前运行的服务器根目录的。然而,当你直接通过文件系统协议
(file://)打开index.html
时,这些相对路径可能无法正确解析,尤其是当资源文件位于index.html所在目录的子目录下时。
而且还因为同源策略的限制,css和js对于这个index.html来说是不同源的资源,所以也无法获取到,导致整个页面白屏。
还有就是异步请求,在开发环境时会有代理,但是打包是不会将代理一起打包进去,所以会跨域。
为了避免这些问题,正确的做法是在本地启动一个简单的HTTP服务器
来托管dist文件夹中的内容。这样可以确保资源路径正确解析,同时避免跨域限制,使得动态加载资源的请求能够被正确处理。
9. springboot请求第三方服务器返回数据乱码问题
一般是因为第三方服务器返回的数据编码格式不是UTF-8导致的。
所以需要限制第三方服务器返回数据的编码格式。
springboot一般用restTemplate来请求第三方服务器,只需要在请求前添加以下代码即可。
// 请求前手动设置UTF-8编码解析报文体
restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
这样从第三方请求回来的数据就是UTF-8编码的了,没有乱码问题。
tips
如果请求头使用的是application/x-www-form-urlencoded
,那么就需要在请求前手动设置Content-Type
为application/x-www-form-urlencoded
。
// 创建HttpHeaders对象并设置多个请求头
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
如果传参使用的是Map
,那么就需要将Map
转成MultiValueMap
。
MultiValueMap<String,Object> params = new LinkedMultiValueMap<>();
params.add("name","小明");
10. Git Commit 提交代码如何取消代码校验
使用别人的项目进行二次开发时,一般会将代码上传到自己的仓库当中进行保存。
在提交代码时,因为某些项目会有设定好的代码校验规则,有时候会出现代码校验失败的情况,这时候就需要取消代码校验。
在提交代码时,加上--no-verify
参数即可。
git commit -m "提交代码" --no-verify
如果不想次次上传代码都加上这个参数,也可以采用以下方法:
进入.git/hooks
文件夹,将hooks
文件夹中的所有文件删除
!直接删除全部的文件,不要删除文件夹。
再重新执行代码提交commit就不会有代码校验的问题了。
11. Vscode的终端无法使用pnpm命令
在vscode终端里使用pnpm命令时,会提示pnpm : 无法加载文件 D:\Program Files\pnpm\pnpm.ps1,因为在此系统上禁止运行脚本
。
解决方法:
在vscode终端里执行以下命令:
#更改vscode终端的状态
Set-ExecutionPolicy RemoteSigned
然后再执行pnpm命令就可以了。
记得将pnpm远程仓库设置成镜像仓库地址:
pnpm set config registry https://registry.npmmirror.com/
pnpm set registry https://registry.npmmirror.com/
解释:
Set-ExecutionPolicy RemoteSigned
是一个 PowerShell 命令,用于更改 PowerShell 脚本的执行策略。这个特定的设置允许你运行本地创建的脚本,而从 Internet 下载的脚本必须有一个数字签名才能运行。
这里是各种执行策略的简要概述:
Restricted
:这是默认设置,不允许运行任何 PowerShell 脚本。AllSigned
:只允许运行经过数字签名的脚本。RemoteSigned
:允许运行本地创建的脚本。从 Internet 下载的脚本必须有一个数字签名才能运行。Unrestricted
:允许运行所有脚本。
12. localstorage可以多页面通信,但是sessionstorage不行
在MDN
的解释中:
只读的localStorage
属性允许你访问一个Document
源(origin)的对象 Storage
;存储的数据将保存在浏览器会话中。localStorage
类似 sessionStorage
,但其区别在于:存储在 localStorage
的数据可以长期保留;而当页面会话结束——也就是说,当页面被关闭时,存储在 sessionStorage
的数据会被清除。
所以localStorage
是可以多页面通信的。
那么sessionStorage
呢?
- 页面会话在浏览器打开期间一直保持,并且重新加载或恢复页面仍会保持原来的页面会话。
- 在新标签或窗口打开一个页面时会
复制
顶级浏览会话的上下文作为新会话的上下文,这点和 session cookie 的运行方式不同。 - 打开多个相同的 URL 的 Tabs 页面,会创建各自的
sessionStorage
。 - 关闭对应浏览器标签或窗口,会清除对应的
sessionStorage
。
sessionStorage
不能在多个窗口或标签页之间共享数据,但是当通过 window.open
或链接打开新页面时(不能是新窗口),新页面会复制前一页的 sessionStorage
。
sessionStorage
就是会话级别的存储(关键在于会话)
如何定义一个会话?
在A页面点击超链接或者在控制台window.open打开页面B,都是属于当前页面的延续,属于一个会话
。
在A页面已经打开的前提下,然后在新tab打开同域页面C,此时C和A页面无直接关系,不属于
一个会话。
上文中已经说了的,sessionStorage
并不是共享的,而是复制的。
B页面打开的时候复制了A页面的sessionStorage
,仅仅是复制
此时,无论修改A页面的sessionStorage
还是修改B页面的SessionStorage
,都不会彼此影响。