0

I am trying to upload a file via a POST request. Using the HttpRequestMessage<File> gives me the error below. If I use HttpRequestMessage<byte[]> the code works but I am missing the meta-data like file name and other details which I need to upload as well.

Code:

@FunctionName("HttpExample")
    public String run(@HttpTrigger(name = "req", methods = { HttpMethod.GET,
            HttpMethod.POST }, authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<File> request,
            final ExecutionContext context) { ... }

Error:

Executed 'Functions.HttpExample' (Failed, Id=7349f061-9213-4607-a757-8231c41078d2)
[27/02/2020 10:18:15] System.Private.CoreLib: Exception while executing function: Functions.HttpExample. System.Private.CoreLib: Result: Failure
[27/02/2020 10:18:15] Exception: ClassCastException: Cannot convert com.microsoft.azure.functions.worker.binding.RpcHttpRequestDataSource@74386ca9to type com.microsoft.azure.functions.HttpRequestMessage<java.io.File>
[27/02/2020 10:18:15] Stack: java.lang.ClassCastException: Cannot convert com.microsoft.azure.functions.worker.binding.RpcHttpRequestDataSource@74386ca9to type com.microsoft.azure.functions.HttpRequestMessage<java.io.File>
[27/02/2020 10:18:15]   at com.microsoft.azure.functions.worker.binding.DataOperations.generalAssignment(DataOperations.java:191)
[27/02/2020 10:18:15]   at com.microsoft.azure.functions.worker.binding.DataOperations.apply(DataOperations.java:120)
[27/02/2020 10:18:15]   at com.microsoft.azure.functions.worker.binding.DataSource.computeByType(DataSource.java:56)
[27/02/2020 10:18:15]   at com.microsoft.azure.functions.worker.binding.RpcHttpRequestDataSource.computeByType(RpcHttpRequestDataSource.java:20)
[27/02/2020 10:18:15]   at com.microsoft.azure.functions.worker.binding.DataSource.computeByName(DataSource.java:42)
[27/02/2020 10:18:15]   at com.microsoft.azure.functions.worker.binding.RpcHttpRequestDataSource.computeByName(RpcHttpRequestDataSource.java:20)
[27/02/2020 10:18:15]   at com.microsoft.azure.functions.worker.binding.BindingDataStore.getDataByName(BindingDataStore.java:55)
[27/02/2020 10:18:15]   at com.microsoft.azure.functions.worker.broker.ParameterResolver.resolve(ParameterResolver.java:59)
[27/02/2020 10:18:15]   at com.microsoft.azure.functions.worker.broker.ParameterResolver.resolve(ParameterResolver.java:42)
[27/02/2020 10:18:15]   at com.microsoft.azure.functions.worker.broker.JavaMethodExecutor.execute(JavaMethodExecutor.java:52)
[27/02/2020 10:18:15]   at com.microsoft.azure.functions.worker.broker.JavaFunctionBroker.invokeMethod(JavaFunctionBroker.java:53)
[27/02/2020 10:18:15]   at com.microsoft.azure.functions.worker.handler.InvocationRequestHandler.execute(InvocationRequestHandler.java:33)
[27/02/2020 10:18:15]   at com.microsoft.azure.functions.worker.handler.InvocationRequestHandler.execute(InvocationRequestHandler.java:10)
[27/02/2020 10:18:15]   at com.microsoft.azure.functions.worker.handler.MessageHandler.handle(MessageHandler.java:45)
[27/02/2020 10:18:15]   at com.microsoft.azure.functions.worker.JavaWorkerClient$StreamingMessagePeer.lambda$onNext$0(JavaWorkerClient.java:92)
[27/02/2020 10:18:15]   at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
[27/02/2020 10:18:15]   at java.util.concurrent.FutureTask.run(FutureTask.java:266)
[27/02/2020 10:18:15]   at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
[27/02/2020 10:18:15]   at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
[27/02/2020 10:18:15]   at java.lang.Thread.run(Thread.java:748)
[27/02/2020 10:18:15] .
IrtzaSuhail
  • 97
  • 1
  • 9

1 Answers1

0

It is impossible to directly use File. There is not implementation for converting your request to HttpRequestMessage<java.util.Optional<java.io.File>>.

A solution is to upload file with multipart/form-data. There is already a post about this, you may refer to: upload with multipart/form-data. There is also a known problem: Azure function will lose some unreadable bytes, to solve it, you may see the update in that answer.

Another easier solution, is to keep using byte array. However, at the same time, you may put the file name and other metadatas into query parameters. For example: ?filename=xxx&other=xxxx.

Then you can get file content from byte array, and all the metadatas from query parameters:

    @FunctionName("HttpExample")
    public HttpResponseMessage run(
            @HttpTrigger(name = "req", methods = {HttpMethod.GET, HttpMethod.POST}, authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Optional<byte[]>> request,
            final ExecutionContext context) {
        context.getLogger().info("Java HTTP trigger processed a request.");

        byte[] body = request.getBody().get();

        Map<String, String> queryParameters = request.getQueryParameters();
        String fileName = queryParameters.get("fileName");

        return request.createResponseBuilder(HttpStatus.OK).body(fileName + " -> " + new String(body)).build();
    }

enter image description here

Jack Jia
  • 5,268
  • 1
  • 12
  • 14