问题描述
我有一个 Quarkus 服务,我正在尝试(在某种程度上)模仿 S3 API。
我注意到 S3 中的分段上传是这样的:
POST bucket.host.com /KEY?uploads // signifies that a multipart upload on KEY is starting
// and returns an uploadId for it
PUT bucket.host.com /KEY?uploadId=UPLOADID&partNumber=2 // uploads part 2 of the file,// content is in request body
PUT bucket.host.com /KEY?uploadId=UPLOADID&partNumber=1 // upload part 1
POST bucket.host.com /KEY?uploadId=UPLOADID // signifies that the multipart upload is completed
“原子”文件上传(即,没有分段,文件只是一次性上传)“重用”PUT 路径,因此要以这种方式上传文件,您只需在 URL 上执行 PUT 并跳过两者查询参数。
我不会使用“存储桶嵌入在主机名中”的方法,而是将其作为请求 URL 的一部分。
所以我目前拥有的是一个看起来像这样的资源类(在我的例子中简化了,bucket 被称为“project”,KEY 被称为“path”):
@Path("/fts")
class FileTransferService(
@ConfigProperty(name = "fts.project.root")
private val projectRoot: String
) {
@POST
@Path("{project}/{path:.*}")
@Produces(MediaType.APPLICATION_JSON)
fun multipartfileUpload(
@PathParam project: String,@PathParam path: String,@QueryParam("uploads") uploads: String?,@QueryParam("uploadId") uploadId: String?
): String {
// Here I'll have to check whether uploads or uploadId is set
// and determine the path to take with some if/else statements.
}
@PUT
@Path("{project}/{path:.*}")
@Produces(MediaType.APPLICATION_JSON)
fun upload(
@PathParam project: String,@QueryParam("uploadId") uploadId: String?,@QueryParam("partNumber") partNumber: String?,body: InputStream
): String {
// Here I'll need to check uploadId and/or partNumber to determine
// whether this is an "atomic file upload" or a single part of a
// multi part upload and determine the path to take with if/else again.
}
}
正如你在上面代码的注释中看到的,我必须做一些 if/else 检查并根据查询参数是否设置走不同的路线。
这让我很烦。我宁愿有不同的@POST 方法,一种是设置 uploads
参数的情况,另一种是设置 uploadId
参数的情况。
我尝试了多种方法,其中一个指定了 QueryParameter,而另一个没有,但这似乎不起作用。我在 quarkus 日志中收到一条信息消息,指出为该路径找到了多个匹配项,并且随机选择了一个匹配项(可能只是第一个匹配项)。
所以我猜测,如果这完全可行,它会以某种方式将查询参数放入 @Path
注释中,但我一直无法找到如何做到这一点。一个可能的原因是这是不可能的,但我想在这里询问并获得确认。
解决方法
如果您想使用查询参数,您当前的版本是正确的。
您将无法使用 JAX-RS 做您想做的事。路径决定了调用的方法,查询参数只是可选的附加信息。
如果你绝对想根据参数存在有不同的方法,你需要使用路径参数。