0

我正在使用Uppy 的 Vue 组件来处理上传大文件,但我无法让它工作。

我遵循了 Janko 的建议,其中包括在 Uppy 中设置同伴Url 以指向我的服务器,然后编写必要的路由/函数来处理请求。

在我尝试触发 AWS“completeMultipartUpload”调用之前,一切正常。

$result = $client->completeMultipartUpload([
    'Bucket'          => 'bucket-name',
    'Key'             => $key,
    'UploadId'        => $uploadId,
    'MultipartUpload' => [
        'Parts' => $formattedParts,
    ],
]);

我收到以下错误:

"Error executing "CompleteMultipartUpload" on "https://bucket-name.s3.amazonaws.com/NewProject.png?uploadId=nlWLdbNgB9zgarpLBXnj17eOIGAmQM_xyBArymtwdM71fhbFvveggDmL6fz4blz.B95TLhMatDvodbMb5p2ZMKqdlLeLFoSW1qcu33aRQTlt6NbiP_dkDO90DFO.pWGH"; AWS HTTP error: Client error: `POST https://bucket-name.s3.amazonaws.com/NewProject.png?uploadId=nlWLdbNgB9zgarpLBXnj17eOIGAmQM_xyBArymtwdM71fhbFvveggDmL6fz4blz.B95TLhMatDvodbMb5p2ZMKqdlLeLFoSW1qcu33aRQTlt6NbiP_dkDO90DFO.pWGH` resulted in a `400 Bad Request` response:
    <Error><Code>InvalidPart</Code><Message>One or more of the specified parts could not be found.  The part may not have be (truncated...)
    InvalidPart (client): One or more of the specified parts could not be found.  The part may not have been uploaded, or the specified entity tag may not match the part's entity tag. - <Error><Code>InvalidPart</Code><Message>One or more of the specified parts could not be found.  The part may not have been uploaded, or the specified entity tag may not match the part's en"

我认为问题在于我已经尝试将这里找到的 JS 翻译成 PHP,但是虽然它返回了一个 URL,但它是不正确的。显着的区别是我没有传递“UploadId”或“PartNumber”。

我搜索了 AWS 文档、Google、Stackoverflow、Ask Jeeves 等,但找不到与“getSignedUrl”方法等效的 PHP

public function signPartUpload(Request $request, $uploadId, $partNumber)
{
    $client = new S3Client([
        'version' => 'latest',
        'region'  => 'us-east-1',
    ]);

    $key = $request->has('key') ? $request->get('key') : null;

    if (!is_string($key)) {
        return response()->json(['error' => 's3: the object key must be passed as a query parameter. For example: "?key=abc.jpg"'], 400);
    }

    if (!intval($partNumber)) {
        return response()->json(['error' => 's3: the part number must be a number between 1 and 10000.'], 400);
    }

    //Creating a presigned URL
    $cmd = $client->getCommand('PutObject', [
        'Bucket' => 'bucket-name',
        'Key' => $key
    ]);

    $response = $client->createPresignedRequest($cmd, '+20 minutes');
    $presignedUrl = (string)$response->getUri();

    return response()->json(['url' => $presignedUrl]);
}

任何帮助将不胜感激!

4

1 回答 1

0

我找到了该方法的 PHP 等效项getSignedUrl

$command = $this->client->getCommand('UploadPart', [
    'Bucket'        => $this->bucket,
    'Key'           => $key,
    'PartNumber'    => $partNumber,
    'UploadId'      => $uploadId,
    'Body'          => '',
]);

这是我的解决方案:

/**
 * Create a pre-signed URL for parts to be uploaded to.
 * @param Request $request
 * @param string $uploadId
 * @param int $partNumber
 * @return JsonResponse
 */
public function signPartUpload(Request $request, string $uploadId, int $partNumber)
{
    $key = $request->has('key') ? $request->get('key') : null;

    // Check key
    if (! is_string($key)) {
        return response()->json(['error' => 's3: the object key must be passed as a query parameter. For example: "?key=abc.jpg"'], 400);
    }

    // Check part number
    if (! intval($partNumber)) {
        return response()->json(['error' => 's3: the part number must be a number between 1 and 10000.'], 400);
    }

    // Create the upload part command and get the pre-signed URL
    try {
        $command = $this->client->getCommand('UploadPart', [
            'Bucket'        => $this->bucket,
            'Key'           => $key,
            'PartNumber'    => $partNumber,
            'UploadId'      => $uploadId,
            'Body'          => '',
        ]);

        $presignedUrl = $this->client->createPresignedRequest($command, '+20 minutes');
    } catch (Exception $e) {
        return response()->json(['error' => $e->getMessage()], 400);
    }

    // Convert the pre-signed URL to a string
    $presignedUrlString = (string) $presignedUrl->getUri();

    return response()->json(['url' => $presignedUrlString]);
}
于 2021-04-27T15:03:26.197 回答