Repository: AlistGo/alist (language: go)

Issue:
[Bug] 使用webdav put方法chunked形式上传文件时,因Content-Length值的问题导致返回405
### 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.27.0

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

any

### Describe the bug / 问题描述

使用webdav上传文件时,当content的内容长度未知时,会使用`chunked`模式来上传,这种情况下header中不会填写Content-Length,但在alist的http处理中(不确定是Gin还是net.http的行为)会把`http.Request.ContentLength`置为-1.

于是在这段代码中`pkg/utils/file.go`:  
`size`的最终实际取值是`http.Request.ContentLength`,即-1,导致返回了错误.  
我建议将`size != 0`修改为`size > 0`,以支持chunked模式
```go
// CreateTempFile create temp file from io.ReadCloser, and seek to 0
func CreateTempFile(r io.Reader, size int64) (*os.File, error) {
        ....
	if size != 0 && readBytes != size {
		_ = os.Remove(f.Name())
		return nil, errs.NewErr(err, "CreateTempFile failed, incoming stream actual size= %d, expect = %d ", readBytes, size)
	}
	....
	return f, nil
}
```
同时建议`internal/stream/stream.go`中的`FileStream`的`GetSize()`方法,如果已经存了临时文件就先取临时文件的长度,以减少以上场景取到无效的Size.像这样:
```golang
type FileStream struct {
	Ctx context.Context
	model.Obj
	io.Reader
	Mimetype     string
	WebPutAsTask bool
	Exist        model.Obj //the file existed in the destination, we can reuse some info since we wil overwrite it
	utils.Closers
	tmpFile  *os.File //if present, tmpFile has full content, it will be deleted at last
	peekBuff *bytes.Reader
}

func (f *FileStream) GetSize() int64 {
	if f.tmpFile != nil {
		info, err := f.tmpFile.Stat()
		if err == nil {
			return info.Size()
		}
	}
	return f.Obj.GetSize()
}
```
我愿意提一个PR来修改这个问题

### Reproduction / 复现链接

无

### Config / 配置

无

### Logs / 日志

```bash
ERRO[2023-09-04 08:52:19] PUT /dav/quark/photos/2023/09/02/20230902012905_20230902_132905.JPG %!w(<nil>); CreateTempFile failed, incoming stream actual size= 2786239, expec
t = -1                                                                                github.com/alist-org/alist/v3/internal/op.Put                                         
        /app/internal/op/fs.go:566                                                    
```


Discussion / hints:

Fix patch:
diff --git a/internal/stream/stream.go b/internal/stream/stream.go
index 8bc27b3a4d3..a45735d035a 100644
--- a/internal/stream/stream.go
+++ b/internal/stream/stream.go
@@ -26,6 +26,16 @@ type FileStream struct {
 	peekBuff *bytes.Reader
 }
 
+func (f *FileStream) GetSize() int64 {
+	if f.tmpFile != nil {
+		info, err := f.tmpFile.Stat()
+		if err == nil {
+			return info.Size()
+		}
+	}
+	return f.Obj.GetSize()
+}
+
 func (f *FileStream) GetMimetype() string {
 	return f.Mimetype
 }
diff --git a/pkg/utils/file.go b/pkg/utils/file.go
index ada1d5e2a13..31803a95b2d 100644
--- a/pkg/utils/file.go
+++ b/pkg/utils/file.go
@@ -126,7 +126,7 @@ func CreateTempFile(r io.Reader, size int64) (*os.File, error) {
 		_ = os.Remove(f.Name())
 		return nil, errs.NewErr(err, "CreateTempFile failed")
 	}
-	if size != 0 && readBytes != size {
+	if size > 0 && readBytes != size {
 		_ = os.Remove(f.Name())
 		return nil, errs.NewErr(err, "CreateTempFile failed, incoming stream actual size= %d, expect = %d ", readBytes, size)
 	}


Test patch: