-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
fix(stream): http chucked upload issue #1152
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
问题出在分块上传的时候,有些sdk的实现不会传入Content-Length, 导致f.GetSize()返回0 OpenList/internal/stream/stream.go Line 209 in b0dbbeb
下面的bufSize也就直接变成0了,而这个commit之前是所有cache都直接存入硬盘中,即utils.CreateTempFile,然后file会变成tmpF,之后GetSize()在 http chunk和非http chunk都会获取到正确的文件大小 |
|
原来代码有些地方看着有点跟不上@j2rong4cn的思路,不太会改😢 虽然看起来像爆改,但我已经尽量保留原来的思路了 |
|
我明天有空再改 |
有个疑问,有些云盘在上传前要上报文件大小的,如果是流式上传用不到缓存,这种情况以前不也是会直接失败吗? |
有点没理解,是指的是原issue复现代码的情况吗 |
在b0dbbeb 之前流式上传也是会默认缓存到硬盘上的 你可以git revert 8c244a9 然后断点在 OpenList/server/handles/fsup.go Line 61 in 8c244a9
然后再git pull,再走一次上传流程,再断点在 OpenList/internal/stream/stream.go Line 141 in 4f2de93
跟着往下走就大概理解怎么回事了 复现代码可以用这个 点击展开/折叠代码 |
|
|
4.1.0吗,我试试 |
直接网页端传吗,还是用代码,我复现不了 |
|
治标不治本,例如在 我觉得应该添加 File-Size 请求头 OpenList/server/handles/fsup.go Lines 59 to 67 in f350ccd
|
我试了一下chunk分支merge过来流式上传是没问题
|
搞错了,As-Task请求头为false,是不能分片 |
|
#1100 的代码,合并这个 PR 后能上传
完整测试代码: src\main\java\com\example\FileUploader.java package com.example;
import cn.hutool.core.io.resource.ResourceUtil;
import cn.hutool.http.Header;
import cn.hutool.http.HttpConfig;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import java.io.File;
public class FileUploader {
public static void main(String[] args) {
try {
// 配置HTTP参数
HttpConfig httpConfig = new HttpConfig()
// 分块模式,每块50MB
.setBlockSize(1024 * 1024 * 50);
// 要上传的文件路径(请根据实际情况修改)
String filePath = "e:\\xxx\\2GB.bin";
// 检查文件是否存在
File file = new File(filePath);
if (!file.exists()) {
System.err.println("错误:文件不存在 - " + filePath);
return;
}
System.out.println("开始上传文件: " + filePath);
System.out.println("文件大小: " + file.length() + " 字节");
// 发送HTTP PUT请求上传文件
HttpResponse response = HttpRequest.put("http://10.0.1.111:5244/api/fs/put")
.timeout(1000 * 60 * 2) // 超时时间2分钟
.setConfig(httpConfig)
.header(Header.AUTHORIZATION, "eyJxxx.xxx.xxx") // 请替换为实际的授权token
.header("As-Task", "true")
.header("File-Path", "/123/Temp") // 服务器上的目标路径
.header(Header.CONTENT_LENGTH, String.valueOf(file.length()))
.contentType("application/octet-stream")
.body(ResourceUtil.getResourceObj(filePath))
.execute();
// 检查响应结果
if (response.isOk()) {
System.out.println("文件上传成功!");
System.out.println("响应状态码: " + response.getStatus());
System.out.println("响应内容: " + response.body());
} else {
System.err.println("文件上传失败!");
System.err.println("响应状态码: " + response.getStatus());
System.err.println("错误信息: " + response.body());
}
} catch (Exception e) {
System.err.println("上传过程中发生错误: " + e.getMessage());
e.printStackTrace();
}
}
}pom.xml <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>file-upload</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- Hutool HTTP工具 -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-http</artifactId>
<version>5.8.22</version>
</dependency>
<!-- Hutool 核心工具 -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-core</artifactId>
<version>5.8.22</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>8</source>
<target>8</target>
</configuration>
</plugin>
<!-- 创建可执行JAR -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.4</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.example.FileUploader</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>测试命令: # 生成随机文件
dd if=/dev/urandom of=2GB.bin bs=1G count=2
# Maven 打包
mvn clean package
# 运行
java -jar target/file-upload-1.0.0.jar |
|
试试 请求头As-Task设置为false, |
|
那是因为这个PR只是修复了 As-Task为true时无法缓存的问题,,缓存之后是可以获取文件大小, |
不合这个 PR,直接改成这样 sizeStr := c.GetHeader("File-Size")
if sizeStr == "" {
sizeStr := c.GetHeader("Content-Length")
if sizeStr == "" {
sizeStr = "0"
}
}然后 JAVA 客户端加上 .header("As-Task", "false")
.header("File-Size", String.valueOf(file.length()))
.header("As-Task", "true")
.header("File-Size", String.valueOf(file.length()))
也可以 内存占用还小
|
|
要不要在客户端没有文件大小的请求头时报错呢? |
xrgzs
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM,记得更新一下文档和 Apifox
* fix(stream): http chucked upload issue * fix(stream): use MmapThreshold * fix(stream): improve caching mechanism and handle size=0 case * fix bug * fix(buffer): optimize ReadAt method for improved performance * fix(upload): handle Content-Length and File-Size headers for better size management * fix(189pc): 移除重复限速 * fix(upload): handle negative file size during streaming uploads * fix(upload): update header key from File-Size to X-File-Size for size retrieval --------- Co-authored-by: j2rong4cn <[email protected]>















流式上传 /api/fs/put 添加
X-File-Size请求头 与Content-Length一样用于传递文件大小,如果两个请求头同时存在优先采用Content-Length,X-File-Size可用于无法传递Content-Length请求头时使用,或者 仅使用X-File-Size(推荐)close #1100