fix(stream): http chucked upload issue#1152
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()))
也可以 内存占用还小
|
|
要不要在客户端没有文件大小的请求头时报错呢? |
* 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 <j2rong@qq.com>















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