Skip to content
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

对象存储不能支持上传多级文件 #6588

Closed
4 tasks done
akang943578 opened this issue Jun 7, 2024 · 22 comments
Closed
4 tasks done

对象存储不能支持上传多级文件 #6588

akang943578 opened this issue Jun 7, 2024 · 22 comments
Labels
bug Something isn't working

Comments

@akang943578
Copy link
Contributor

akang943578 commented Jun 7, 2024

Please make sure of the following things

  • I have read the documentation.
    我已经阅读了文档

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

  • I'm sure it's due to AList and not something else(such as Network ,Dependencies or Operational).
    我确定是AList的问题,而不是其他原因(例如网络依赖操作)。

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

AList Version / AList 版本

v3.35.0

Driver used / 使用的存储驱动

Aliyun Open

Describe the bug / 问题描述

我根据文档进行对象存储的配置,挂载了阿里云盘已经存在的目录作为存储桶,给seafile配置存储桶作为存储后端。

配置完成后,在seafile创建资料库报错:

2024-06-07 19:04:29 ../common/s3-client.c(842): Request URL: http://172.17.0.1:5246/seafile-commit-objects/9d8233b0-d9e9-4c5f-a5de-0a9ac8f7899d/6dd1cd17494cd27d7d9b21ca07c562a686403acf
2024-06-07 19:04:29 ../common/s3-client.c(843): Request headers:
2024-06-07 19:04:29 ../common/s3-client.c(731): Date: Fri, 07 Jun 2024 11:04:29 GMT
2024-06-07 19:04:29 ../common/s3-client.c(731): Authorization: AWS NXM00iAJpLvPYC94VRDd:q20e3MP/dZOpnzBZTvo619ONSpU=
2024-06-07 19:04:29 ../common/obj-backend-s3.c(354): Put object 6dd1cd17494cd27d7d9b21ca07c562a686403acf error 400. Response:
<?xml version="1.0" encoding="UTF-8"?>
<errorResponse><Code>UnsupportedAlgorithm</Code><Message>Encountered an unsupported algorithm.</Message></errorResponse>
2024-06-07 19:04:29 repo-mgr.c(7638): Failed to add commit.

我发现这个请求URL中,seafile-commit-objects在阿里云盘已经存在,9d8233b0-d9e9-4c5f-a5de-0a9ac8f7899d/6dd1cd17494cd27d7d9b21ca07c562a686403acf这个是要创建的文件路径,我发现这是个二级路径,说明需要创建目录9d8233b0-d9e9-4c5f-a5de-0a9ac8f7899d。
但是看文档,应该是不支持目录的创建:

目前仅支持使用客户端 获取列表、下载、上传、删除 操作,其它操作暂未支持

经过我自己用python脚本测试,发现不需要创建目录的时候可以成功,一旦需要创建目录,就会失败。可否支持目录的创建和删除?

Reproduction / 复现链接

https://alist.nn.ci/zh/guide/advanced/s3.html

Config / 配置

{
  "force": false,
  "site_url": "",
  "cdn": "",
  "jwt_secret": "8QDQ5NTHjNKTQIND",
  "token_expires_in": 48,
  "database": {
    "type": "sqlite3",
    "host": "",
    "port": 0,
    "user": "",
    "password": "",
    "name": "",
    "db_file": "data/data.db",
    "table_prefix": "x_",
    "ssl_mode": "",
    "dsn": ""
  },
  "meilisearch": {
    "host": "http://localhost:7700",
    "api_key": "",
    "index_prefix": ""
  },
  "scheme": {
    "address": "0.0.0.0",
    "http_port": 5244,
    "https_port": -1,
    "force_https": false,
    "cert_file": "",
    "key_file": "",
    "unix_file": "",
    "unix_file_perm": ""
  },
  "temp_dir": "data/temp",
  "bleve_dir": "data/bleve",
  "dist_dir": "",
  "log": {
    "enable": true,
    "name": "data/log/log.log",
    "max_size": 10,
    "max_backups": 5,
    "max_age": 28,
    "compress": false
  },
  "delayed_start": 0,
  "max_connections": 0,
  "tls_insecure_skip_verify": false,
  "tasks": {
    "download": {
      "workers": 5,
      "max_retry": 1
    },
    "transfer": {
      "workers": 5,
      "max_retry": 2
    },
    "upload": {
      "workers": 5,
      "max_retry": 0
    },
    "copy": {
      "workers": 5,
      "max_retry": 2
    }
  },
  "cors": {
    "allow_origins": [
      "*"
    ],
    "allow_methods": [
      "*"
    ],
    "allow_headers": [
      "*"
    ]
  },
  "s3": {
    "enable": true,
    "port": 5246,
    "ssl": false
  }
}

Logs / 日志

2024-06-07 19:04:29 ../common/s3-client.c(842): Request URL: http://172.17.0.1:5246/seafile-commit-objects/9d8233b0-d9e9-4c5f-a5de-0a9ac8f7899d/6dd1cd17494cd27d7d9b21ca07c562a686403acf
2024-06-07 19:04:29 ../common/s3-client.c(843): Request headers:
2024-06-07 19:04:29 ../common/s3-client.c(731): Date: Fri, 07 Jun 2024 11:04:29 GMT
2024-06-07 19:04:29 ../common/s3-client.c(731): Authorization: AWS NXM00iAJpLvPYC94VRDd:q20e3MP/dZOpnzBZTvo619ONSpU=
2024-06-07 19:04:29 ../common/obj-backend-s3.c(354): Put object 6dd1cd17494cd27d7d9b21ca07c562a686403acf error 400. Response:
<?xml version="1.0" encoding="UTF-8"?>
<errorResponse><Code>UnsupportedAlgorithm</Code><Message>Encountered an unsupported algorithm.</Message></errorResponse>
2024-06-07 19:04:29 repo-mgr.c(7638): Failed to add commit.
@akang943578 akang943578 added the bug Something isn't working label Jun 7, 2024
Copy link

welcome bot commented Jun 7, 2024

Thanks for opening your first issue here! Be sure to follow the issue template!

@itsHenry35
Copy link
Member

已知bug,近期比较忙,过段时间再修

@akang943578
Copy link
Contributor Author

akang943578 commented Jun 27, 2024

感谢支持,我利用闲暇时间经过测试,已经定位修复了问题,为此提交了一个PR:#6660

希望大佬可以review下,如果可以的话,还请帮忙merge进去,感激不尽!

@itsHenry35
Copy link
Member

我测试了一下,貌似本地路径还是无法上传多级的文件欸,你测试过吗
image

@akang943578
Copy link
Contributor Author

我测试了一下,貌似本地路径还是无法上传多级的文件欸,你测试过吗 image

抱歉大佬,我只在网页端测试了,windows端我一会测试一下,应该是路径判断有问题,我直接判断的是否含有/

@itsHenry35
Copy link
Member

我测试了一下,貌似本地路径还是无法上传多级的文件欸,你测试过吗 image

抱歉大佬,我只在网页端测试了,windows端我一会测试一下,应该是路径判断有问题,我直接判断的是否含有/

不用抱歉,大家平等交流就好😊我也不是什么特别厉害的大佬,这个问题就是因为我也觉得有点棘手,所以一直没时间弄哈哈哈

@akang943578
Copy link
Contributor Author

akang943578 commented Jun 28, 2024

我测试了一下,貌似本地路径还是无法上传多级的文件欸,你测试过吗 image

抱歉大佬,我只在网页端测试了,windows端我一会测试一下,应该是路径判断有问题,我直接判断的是否含有/

不用抱歉,大家平等交流就好😊我也不是什么特别厉害的大佬,这个问题就是因为我也觉得有点棘手,所以一直没时间弄哈哈哈

我们可能说的不是一个问题,我解决的问题是:

alist实现的S3对象存储协议不能够支持:上传文件时,objectName存在多级路径

比如有一个bucket: bucketName1,指向了阿里云盘的目录/root/path/storage。此时如果通过S3协议上传一个文件:

PUT https://s3.example.com/bucketName1/aaa/bbb.txt

alist会直接去找上一级目录:/root/path/storage/aaa,这个目录不存在,则会直接报错。

我的修复逻辑是:在S3协议的实现中,如果检测到了目录不存在,且objectName含有/,说明是个多级的objectName,则创建这个多级目录。

我在网页端和windows客户端都进行了测试,没有问题。

你的截图是怎样的操作流程,可以描述下吗,可能是另一个问题。

@itsHenry35
Copy link
Member

我测试了一下,貌似本地路径还是无法上传多级的文件欸,你测试过吗 image

抱歉大佬,我只在网页端测试了,windows端我一会测试一下,应该是路径判断有问题,我直接判断的是否含有/

不用抱歉,大家平等交流就好😊我也不是什么特别厉害的大佬,这个问题就是因为我也觉得有点棘手,所以一直没时间弄哈哈哈

我们可能说的不是一个问题,我解决的问题是:

alist实现的S3对象存储协议不能够支持:上传文件时,objectName存在多级路径

比如有一个bucket: bucketName1,指向了阿里云盘的目录/root/path/storage。此时如果通过S3协议上传一个文件:

PUT https://s3.example.com/bucketName1/aaa/bbb.txt

alist会直接去找上一级目录:/root/path/storage/aaa,这个目录不存在,则会直接报错。我的修复逻辑是:在S3协议的实现中,如果检测到了目录不存在,且objectName含有/,说明是个多级的objectName,则创建这个多级目录。

我在网页端和windows客户端都进行了测试,没有问题。

你的截图是怎样的操作流程,可以描述下吗,可能是另一个问题。

就是上传一整个文件夹,或者创建文件夹的操作。

@akang943578
Copy link
Contributor Author

我测试了一下,貌似本地路径还是无法上传多级的文件欸,你测试过吗 image

抱歉大佬,我只在网页端测试了,windows端我一会测试一下,应该是路径判断有问题,我直接判断的是否含有/

不用抱歉,大家平等交流就好😊我也不是什么特别厉害的大佬,这个问题就是因为我也觉得有点棘手,所以一直没时间弄哈哈哈

我们可能说的不是一个问题,我解决的问题是:

alist实现的S3对象存储协议不能够支持:上传文件时,objectName存在多级路径

比如有一个bucket: bucketName1,指向了阿里云盘的目录/root/path/storage。此时如果通过S3协议上传一个文件:

PUT https://s3.example.com/bucketName1/aaa/bbb.txt

alist会直接去找上一级目录:/root/path/storage/aaa,这个目录不存在,则会直接报错。我的修复逻辑是:在S3协议的实现中,如果检测到了目录不存在,且objectName含有/,说明是个多级的objectName,则创建这个多级目录。
我在网页端和windows客户端都进行了测试,没有问题。
你的截图是怎样的操作流程,可以描述下吗,可能是另一个问题。

就是上传一整个文件夹,或者创建文件夹的操作。

我懂了,是一样的问题,我应该将我的修复逻辑下沉一级,这样就能够支持了。目前我怕影响其他功能,只是在S3协议这一级做了修复。

@akang943578
Copy link
Contributor Author

我测试了一下,貌似本地路径还是无法上传多级的文件欸,你测试过吗 image

抱歉大佬,我只在网页端测试了,windows端我一会测试一下,应该是路径判断有问题,我直接判断的是否含有/

不用抱歉,大家平等交流就好😊我也不是什么特别厉害的大佬,这个问题就是因为我也觉得有点棘手,所以一直没时间弄哈哈哈

我们可能说的不是一个问题,我解决的问题是:

alist实现的S3对象存储协议不能够支持:上传文件时,objectName存在多级路径

比如有一个bucket: bucketName1,指向了阿里云盘的目录/root/path/storage。此时如果通过S3协议上传一个文件:

PUT https://s3.example.com/bucketName1/aaa/bbb.txt

alist会直接去找上一级目录:/root/path/storage/aaa,这个目录不存在,则会直接报错。我的修复逻辑是:在S3协议的实现中,如果检测到了目录不存在,且objectName含有/,说明是个多级的objectName,则创建这个多级目录。
我在网页端和windows客户端都进行了测试,没有问题。
你的截图是怎样的操作流程,可以描述下吗,可能是另一个问题。

就是上传一整个文件夹,或者创建文件夹的操作。

我懂了,是一样的问题,我应该将我的修复逻辑下沉一级,这样就能够支持了。目前我怕影响其他功能,只是在S3协议这一级做了修复。

我更新了PR,将修复逻辑下沉到了op/fs.go里边,已经测试通过了。不过这样每次在get的时候都会尝试makeDir,会带来多余的IO,以我对代码的理解只能写成这样了。

@itsHenry35
Copy link
Member

我测试了一下,貌似本地路径还是无法上传多级的文件欸,你测试过吗 image

抱歉大佬,我只在网页端测试了,windows端我一会测试一下,应该是路径判断有问题,我直接判断的是否含有/

不用抱歉,大家平等交流就好😊我也不是什么特别厉害的大佬,这个问题就是因为我也觉得有点棘手,所以一直没时间弄哈哈哈

我们可能说的不是一个问题,我解决的问题是:

alist实现的S3对象存储协议不能够支持:上传文件时,objectName存在多级路径

比如有一个bucket: bucketName1,指向了阿里云盘的目录/root/path/storage。此时如果通过S3协议上传一个文件:

PUT https://s3.example.com/bucketName1/aaa/bbb.txt

alist会直接去找上一级目录:/root/path/storage/aaa,这个目录不存在,则会直接报错。我的修复逻辑是:在S3协议的实现中,如果检测到了目录不存在,且objectName含有/,说明是个多级的objectName,则创建这个多级目录。
我在网页端和windows客户端都进行了测试,没有问题。
你的截图是怎样的操作流程,可以描述下吗,可能是另一个问题。

就是上传一整个文件夹,或者创建文件夹的操作。

我懂了,是一样的问题,我应该将我的修复逻辑下沉一级,这样就能够支持了。目前我怕影响其他功能,只是在S3协议这一级做了修复。

我更新了PR,将修复逻辑下沉到了op/fs.go里边,已经测试通过了。不过这样每次在get的时候都会尝试makeDir,会带来多余的IO,以我对代码的理解只能写成这样了。

这个每次在get的时候尝试makeDir肯定是不可行的😊所以说这个问题比较棘手,得想办法解决

@akang943578
Copy link
Contributor Author

嗯,看样子需要找到所有的上层入口,在上层按需makeDir,才是比较好的方式。

@itsHenry35
Copy link
Member

你先把pr设成draft吧,重新想想办法吧,等我有空我也试一试

@itsHenry35
Copy link
Member

我测试了一下,貌似本地路径还是无法上传多级的文件欸,你测试过吗 image

抱歉大佬,我只在网页端测试了,windows端我一会测试一下,应该是路径判断有问题,我直接判断的是否含有/

不用抱歉,大家平等交流就好😊我也不是什么特别厉害的大佬,这个问题就是因为我也觉得有点棘手,所以一直没时间弄哈哈哈

我们可能说的不是一个问题,我解决的问题是:

alist实现的S3对象存储协议不能够支持:上传文件时,objectName存在多级路径

比如有一个bucket: bucketName1,指向了阿里云盘的目录/root/path/storage。此时如果通过S3协议上传一个文件:

PUT https://s3.example.com/bucketName1/aaa/bbb.txt

alist会直接去找上一级目录:/root/path/storage/aaa,这个目录不存在,则会直接报错。我的修复逻辑是:在S3协议的实现中,如果检测到了目录不存在,且objectName含有/,说明是个多级的objectName,则创建这个多级目录。
我在网页端和windows客户端都进行了测试,没有问题。
你的截图是怎样的操作流程,可以描述下吗,可能是另一个问题。

就是上传一整个文件夹,或者创建文件夹的操作。

我懂了,是一样的问题,我应该将我的修复逻辑下沉一级,这样就能够支持了。目前我怕影响其他功能,只是在S3协议这一级做了修复。

@akang943578 所以上次说的这个问题还是没完全搞定吧?😂要不你的pr先就解决signature v2的一个问题,这个问题后面再来个PR解决

@akang943578
Copy link
Contributor Author

我测试了一下,貌似本地路径还是无法上传多级的文件欸,你测试过吗 image

抱歉大佬,我只在网页端测试了,windows端我一会测试一下,应该是路径判断有问题,我直接判断的是否含有/

不用抱歉,大家平等交流就好😊我也不是什么特别厉害的大佬,这个问题就是因为我也觉得有点棘手,所以一直没时间弄哈哈哈

我们可能说的不是一个问题,我解决的问题是:

alist实现的S3对象存储协议不能够支持:上传文件时,objectName存在多级路径

比如有一个bucket: bucketName1,指向了阿里云盘的目录/root/path/storage。此时如果通过S3协议上传一个文件:

PUT https://s3.example.com/bucketName1/aaa/bbb.txt

alist会直接去找上一级目录:/root/path/storage/aaa,这个目录不存在,则会直接报错。我的修复逻辑是:在S3协议的实现中,如果检测到了目录不存在,且objectName含有/,说明是个多级的objectName,则创建这个多级目录。
我在网页端和windows客户端都进行了测试,没有问题。
你的截图是怎样的操作流程,可以描述下吗,可能是另一个问题。

就是上传一整个文件夹,或者创建文件夹的操作。

我懂了,是一样的问题,我应该将我的修复逻辑下沉一级,这样就能够支持了。目前我怕影响其他功能,只是在S3协议这一级做了修复。

@akang943578 所以上次说的这个问题还是没完全搞定吧?😂要不你的pr先就解决signature v2的一个问题,这个问题后面再来个PR解决

抱歉我没有复现你的问题,我在alist网页端直接上传文件夹是可以成功的,然后我的只修复s3也是可以的。我看你的截图,是winscp连接的s3吗,由于我的alist不是在本机部署,我尝试连接,他就按照bucketname开头的那种url去找,连接是不成功的。或许我们可以约个时间视频一下,看看我到底如何复现

@itsHenry35
Copy link
Member

advanced里面选path-style,就可以连接了,alist现在还没支持host-style的访问

@akang943578
Copy link
Contributor Author

advanced里面选path-style,就可以连接了,alist现在还没支持host-style的访问

好的,我明天试一下

@itsHenry35
Copy link
Member

image

@akang943578
Copy link
Contributor Author

image

我复现并且定位了这个问题。
这个问题是由于WinSCP对于s3上传文件夹的逻辑不太一样,举例说明:
比如要上传这样的目录:testFolder/1.txt

Seafile是直接PutObject, objectName=testFolder/1.txt。按照之前的修复逻辑,testFolder不存在则会makeDir,然后上传1.txt,成功。
而WinSCP则在上述步骤之前,先PutObject, objectName=testFolder,由于Alist S3 backend.go对于PutObject的实现没有区分objectName是目录还是文件,统一按照创建文件处理,则会创建一个testFolder文件。
然后PutObject, objectName=testFolder/1.txt,会去找testFolder目录,发现不存在,尝试makeDir的时候发现已经有一个testFolder文件存在,就失败了。报错:

ERRO[2024-07-03 23:00:39] serve s3: failed to make dir [/testLocal/testInner/testFolder]: file exists 

因此需要在Alist S3 backend.go对于PutObject的实现中,区分objectName是目录还是文件。

这个是WinSCP带来的新问题,可以做一个单独PR去修复,不影响上一个PR的merge。

我后面花些时间看看怎么修复,需要区分objectName是目录还是文件,可能比较麻烦。

@itsHenry35
Copy link
Member

image

我复现并且定位了这个问题。 这个问题是由于WinSCP对于s3上传文件夹的逻辑不太一样,举例说明: 比如要上传这样的目录:testFolder/1.txt

Seafile是直接PutObject, objectName=testFolder/1.txt。按照之前的修复逻辑,testFolder不存在则会makeDir,然后上传1.txt,成功。 而WinSCP则在上述步骤之前,先PutObject, objectName=testFolder,由于Alist S3 backend.go对于PutObject的实现没有区分objectName是目录还是文件,统一按照创建文件处理,则会创建一个testFolder文件。 然后PutObject, objectName=testFolder/1.txt,会去找testFolder目录,发现不存在,尝试makeDir的时候发现已经有一个testFolder文件存在,就失败了。报错:

ERRO[2024-07-03 23:00:39] serve s3: failed to make dir [/testLocal/testInner/testFolder]: file exists 

因此需要在Alist S3 backend.go对于PutObject的实现中,区分objectName是目录还是文件。

这个是WinSCP带来的新问题,可以做一个单独PR去修复,不影响上一个PR的merge。

我后面花些时间看看怎么修复,需要区分objectName是目录还是文件,可能比较麻烦。

嗯,我尝试使用了WinSCP挂载Cloudflare R2, 发现创建目录等操作都是正常的,不知道Cloudflare是如何处理的

@akang943578
Copy link
Contributor Author

WinSCP创建目录的逻辑:请求Path末尾是/,比如 PUT /test-localhost/testFolder/
而创建文件的逻辑:请求Path末尾不是/,比如 PUT /test-localhost/testFolder/1.txt

gofakes3的实现有问题,对path直接进行了Trim截取,这样就直接忽略了末尾的/,都按创建文件来操作了。

https://github.com/alist-org/gofakes3/blob/master/routing.go#L23

但这个截取操作影响所有的S3请求,我可以只修PutObject,但我不知道其他的S3请求是否也存在问题。乱乱乱,或许应该给gofakes3的原作者提一个issue。

@itsHenry35
Copy link
Member

Fixed in 2b74999

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants