Upload para s3 com curl usando URL pré-assinado (obtendo 403)

Estou usando curl para chamar uma API Java ReST para recuperar um URL. O Java gera um URL pré-assinado para o upload do S3 usando minhas credenciais do S3 e o retorna na resposta do ReST. Curl usa o URL e o usa para fazer o upload para o S3, mas o S3 retorna 403 "A assinatura de solicitação que calculamos não corresponde à assinatura que você forneceu. Verifique sua chave e método de assinatura."

Aqui está o código que estou usando para gerar o URL pré-assinado:

public class S3Util {
    static final AmazonS3 s3 = new AmazonS3Client( new AWSCredentials() {
        @Override
        public String getAWSAccessKeyId() {
            return "XXXXXXX";
        }
        @Override
        public String getAWSSecretKey() {
            return "XXXXXXXXXXXXXX";
        }
    });
    static final String BUCKET = "XXXXXXXXXXXXXXXXXXXXXXXXXXX";

    static public URL getMediaChunkURL( MediaChunk mc, HttpMethod method ) {
        String key = ...
        //way in the future (for testing)...
        Date expiration = new Date( System.currentTimeMillis() + CalendarUtil.ONE_MINUTE_IN_MILLISECONDS*60*1000 );

        GeneratePresignedUrlRequest req = new GeneratePresignedUrlRequest(BUCKET, key, method);
        req.setExpiration(expiration);
        req.addRequestParameter("Content-Type", "application/octet-stream");

        //this gets passed to the end user:
        return s3.generatePresignedUrl(req);
    }
}

e em curl, execute a partir do bash, eu executo o seguinte:

echo Will try to upload chunk to ${location}
curl -i -X POST \
        -F 'Content-Type=application/octet-stream' \
        -F "file=@${fileName}" \
        ${location} || (echo upload chunk failed. ; exit 1 )

Entre outras coisas, tentei PUT e tentei "Content-type" (T minúsculo). Percebo que estou perdendo algo (ou algo) óbvio, mas depois de ler os documentos apropriados, pesquisar no Google e examinar muitas perguntas semelhantes, não tenho certeza do que é isso. Vejo muitas dicas sobre os cabeçalhos necessários, mas achei que o URL renunciado deveria eliminar essas necessidades. Talvez não

TIA!

Atualizar

Para deixar claro, testei downloads e isso funciona be

Java parece:

GeneratePresignedUrlRequest req = new GeneratePresignedUrlRequest(BUCKET, key, HttpMethod.GET);
req.setExpiration(expiration);

and curl é simplesmente:

curl -i ${location}

questionAnswers(8)

yourAnswerToTheQuestion