Repository: AlistGo/alist (language: go)

Issue:
百度网盘并发上传时有大概率出错
### Please make sure of the following things

- [X] I have read the [documentation](https://alist.nn.ci).
我已经阅读了[文档](https://alist.nn.ci)。

- [X] I'm sure there are no duplicate issues or discussions.
我确定没有重复的issue或讨论。

- [X] I'm sure it's due to `AList` and not something else(such as [Network](https://alist.nn.ci/faq/howto.html#tls-handshake-timeout-read-connection-reset-by-peer-dns-lookup-failed-connect-connection-refused-client-timeout-exceeded-while-awaiting-headers-no-such-host) ,`Dependencies` or `Operational`).
我确定是`AList`的问题，而不是其他原因（例如[网络](https://alist.nn.ci/zh/faq/howto.html#tls-handshake-timeout-read-connection-reset-by-peer-dns-lookup-failed-connect-connection-refused-client-timeout-exceeded-while-awaiting-headers-no-such-host)，`依赖`或`操作`）。

- [X] I'm sure this issue is not fixed in the latest version.
我确定这个问题在最新版本中没有被修复。


### AList Version / AList 版本

v3.29.1

### Driver used / 使用的存储驱动

百度网盘

### Describe the bug / 问题描述

分几种情况讨论：
1. 百度网盘上传线程数设置为1，同时上传一个文件，一切正常
2. 百度网盘上传线程数设置为1，同时上传多个文件，一切正常
3. 百度网盘上传线程数设置为3，同时上传一个文件，有一定概率出错：报错为{"error_code":31299, "error_msg":"Invalid param keylist"}（partseq>=1的情况）或{"error_code":31299, "error_msg":"Invalid param size"} （partseq == 0的情况）
4. 百度网盘上传线程数设置为3，同时上传多个文件，几乎肯定出错：报错同上。

我是百度网盘VIP，所以chunksize为32MB，不知道在4MB的情况下是否也存在同样问题。

### Reproduction / 复现链接

找两个大小差不多的文件同时进行上传，文件大小超过一个分片即可复现，最好用几百M~1G的，方便复现，我是使用rclone进行同步时复现的：
`.\rclone.exe sync D:\Data\Backup\Test Alist:/baiduDisk/try/test -P --local-encoding None --timeout=1h --transfers=2`

### Config / 配置

全是默认配置，云盘驱动也都是默认配置。

### Logs / 日志

[37mDEBU[0m[2023-12-02 08:38:57]/var/www/alist/drivers/baidu_netdisk/driver.go:317 github.com/alist-org/alist/v3/drivers/baidu_netdisk.(*BaiduNetdisk).uploadSlice() 400 Bad Request{"error_code":31299, "error_msg":"Invalid param keylist"}
[37mDEBU[0m[2023-12-02 08:39:15]/var/www/alist/drivers/baidu_netdisk/driver.go:317 github.com/alist-org/alist/v3/drivers/baidu_netdisk.(*BaiduNetdisk).uploadSlice() 400 Bad Request{"error_code":31299, "error_msg":"Invalid param keylist"} 
[37mDEBU[0m[2023-12-02 08:39:15]/var/www/alist/drivers/baidu_netdisk/driver.go:317 github.com/alist-org/alist/v3/drivers/baidu_netdisk.(*BaiduNetdisk).uploadSlice() 400 Bad Request{"error_code":31299, "error_msg":"Invalid param keylist"}
[37mDEBU[0m[2023-12-02 08:39:16]/var/www/alist/drivers/baidu_netdisk/driver.go:317 github.com/alist-org/alist/v3/drivers/baidu_netdisk.(*BaiduNetdisk).uploadSlice() 400 Bad Request{"error_code":31299, "error_msg":"Invalid param keylist"}
[37mDEBU[0m[2023-12-02 08:39:16]/var/www/alist/drivers/baidu_netdisk/driver.go:317 github.com/alist-org/alist/v3/drivers/baidu_netdisk.(*BaiduNetdisk).uploadSlice() 400 Bad Request{"error_code":31299, "error_msg":"Invalid param keylist"}
[37mDEBU[0m[2023-12-02 08:39:16]/var/www/alist/drivers/baidu_netdisk/driver.go:317 github.com/alist-org/alist/v3/drivers/baidu_netdisk.(*BaiduNetdisk).uploadSlice() 400 Bad Request{"error_code":31299, "error_msg":"Invalid param size"}
[37mDEBU[0m[2023-12-02 08:39:29]/var/www/alist/drivers/baidu_netdisk/driver.go:317 github.com/alist-org/alist/v3/drivers/baidu_netdisk.(*BaiduNetdisk).uploadSlice() 400 Bad Request{"error_code":31299, "error_msg":"Invalid param keylist"}
[37mDEBU[0m[2023-12-02 08:39:46]/var/www/alist/drivers/baidu_netdisk/driver.go:317 github.com/alist-org/alist/v3/drivers/baidu_netdisk.(*BaiduNetdisk).uploadSlice() 400 Bad Request{"error_code":31299, "error_msg":"Invalid param keylist"}
[37mDEBU[0m[2023-12-02 08:39:47]/var/www/alist/drivers/baidu_netdisk/driver.go:317 github.com/alist-org/alist/v3/drivers/baidu_netdisk.(*BaiduNetdisk).uploadSlice() 400 Bad Request{"error_code":31299, "error_msg":"Invalid param keylist"}
[37mDEBU[0m[2023-12-02 08:39:48]/var/www/alist/drivers/baidu_netdisk/driver.go:317 github.com/alist-org/alist/v3/drivers/baidu_netdisk.(*BaiduNetdisk).uploadSlice() 400 Bad Request{"error_code":31299, "error_msg":"Invalid param keylist"}
[37mDEBU[0m[2023-12-02 08:39:48]/var/www/alist/drivers/baidu_netdisk/driver.go:317 github.com/alist-org/alist/v3/drivers/baidu_netdisk.(*BaiduNetdisk).uploadSlice() 400 Bad Request{"error_code":31299, "error_msg":"Invalid param size"}
[37mDEBU[0m[2023-12-02 08:39:48]/var/www/alist/drivers/baidu_netdisk/driver.go:317 github.com/alist-org/alist/v3/drivers/baidu_netdisk.(*BaiduNetdisk).uploadSlice() 400 Bad Request{"error_code":31299, "error_msg":"Invalid param keylist"}

简单跟了下源码，开启resty的debug设置后发现这部分请求其实没有读到文件。
正常情况下的resty debug log:
```
2023/12/02 08:38:45.385910 DEBUG RESTY 
==============================================================================
~~~ REQUEST ~~~
POST  /rest/2.0/pcs/superfile2?access_token=121.xxx&method=upload&partseq=0&path=xxx.mp4&type=tmpfile&uploadid=xxx  HTTP/1.1
HOST   : d.pcs.baidu.com
HEADERS:
	Content-Type: multipart/form-data; boundary=f71ef1962e4331d741886c8e4214ea4abb4f3a9273ef6bb540f43e736532
	User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36
BODY   :
***** REQUEST TOO LARGE (size - 33554664) *****
------------------------------------------------------------------------------
```
异常情况下的resty debug log:
```
2023/12/02 08:38:57.453717 DEBUG RESTY 
==============================================================================
~~~ REQUEST ~~~
POST  /rest/2.0/pcs/superfile2?access_token=121xxx&method=upload&partseq=1&path=xxx.mp4&type=tmpfile&uploadid=xxx  HTTP/1.1
HOST   : d.pcs.baidu.com
HEADERS:
	Content-Type: multipart/form-data; boundary=b0ad7b4e3bdb41b92edde1b08b3da76c57c0b05e716ee12a64b9d08104e8
	Cookie: BAIDUID=xxx; BAIDUID_BFESS=xxx; BAIDUID=xxx; BAIDUID_BFESS=5xxx
	User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36
BODY   :
--b0ad7b4e3bdb41b92edde1b08b3da76c57c0b05e716ee12a64b9d08104e8
Content-Disposition: form-data; name="file"; filename="xxx.mp4"
Content-Type: application/octet-stream


--b0ad7b4e3bdb41b92edde1b08b3da76c57c0b05e716ee12a64b9d08104e8--

------------------------------------------------------------------------------
```


Discussion / hints:
Thanks for opening your first issue here! Be sure to follow the issue template!

对着代码调了一下午，最后发现好像是我自己带宽的问题，因为我的带宽上传只有4M/S的速度，百度网盘VIP一个分片是32MB，就得8s，上传线程填3的话，就得24s才能上传一个分片，如果同时上传两个文件的话一个线程就得48s才能成功，而调用分片上传接口的`base.RestyClient`的默认超时是30s（经过若干次不严谨测试我发现百度服务器的超时似乎也是30s，超过30s百度接口会报500错误）。

而关于resty的问题其实也是个误导，因为`base.RestyClient`设置一个默认的重试次数3，一旦超时，会进入重试，而resty的上传文件方法`SetFileReader`接受的是一个io.Reader，这玩意第一次被读完之后就读不到了，导致了debug log中的file body为空，我也被该现象误导，以为bug出在alist的并发部分或者resty内部。

所以如果是百度会员VIP并且上传带宽又比较小的话，要么一个文件一个文件上传，要么将并发上传数调低。

alist这边感觉也可以优化下restyClient调用分片上传接口的部分，毕竟使用`SetFileReader`的话，resty的重试就没有意义了。
不是大概率，是100%一堆出错
我是从百度网盘向夸克网盘复制，几乎都是出错，然后重试也没用。3个任务一起。

Fix patch:
diff --git a/drivers/base/client.go b/drivers/base/client.go
index bc08d6fb717..8bf8f421eea 100644
--- a/drivers/base/client.go
+++ b/drivers/base/client.go
@@ -33,6 +33,7 @@ func NewRestyClient() *resty.Client {
 	client := resty.New().
 		SetHeader("user-agent", UserAgent).
 		SetRetryCount(3).
+		SetRetryResetReaders(true).
 		SetTimeout(DefaultTimeout).
 		SetTLSClientConfig(&tls.Config{InsecureSkipVerify: conf.Conf.TlsInsecureSkipVerify})
 	return client


Test patch: