使用java中的azure函数将文件从浏览器上传到azure blob存储
Posted
技术标签:
【中文标题】使用java中的azure函数将文件从浏览器上传到azure blob存储【英文标题】:Uploading file from browser to azure blob storage using azure function in java 【发布时间】:2020-01-09 16:50:56 【问题描述】:我正在尝试通过 azure 函数将文件上传到 Azure 存储。我成功上传了纯文本文件,但是对于任何其他类型的文件,这些文件都已损坏。我观察到的是我收到的字节小于实际大小(bodyLength
我尝试将请求数据类型更改为
HttpRequestMessage>抛出的
HttpRequestMessage 和 Byte[]无法转换为byte[] input broken #239[^] 中报告的字符串错误
@FunctionName("上传文件")
公共 HttpResponseMessage 运行(@HttpTrigger(名称 = “请求”,方法 = HttpMethod.GET,
HttpMethod.POST , authLevel = AuthorizationLevel.FUNCTION) HttpRequestMessage(Optional(String>> request,
最终的 ExecutionContext 上下文)
抛出 InvalidKeyException,URISyntaxException,StorageException,IOException
CloudStorageAccount storageAccount = CloudStorageAccount.parse(_storageConnString);
CloudBlobClient blobClient = storageAccount.createCloudBlobClient();
CloudBlobContainer blobContainer = blobClient.getContainerReference(_containerName);
CloudBlockBlob blob = blobContainer.getBlockBlobReference(fileName);
try
String body = request.getBody().get();
long bodyLength = body.length();
String contentLength = request.getHeaders().get("content-length");
InputStream inputStream = new ByteArrayInputStream(body.getBytes());
blob.upload(inputStream, Integer.parseInt(bodyLength));
catch (Exception ex)
return request.createResponseBuilder(HttpStatus.BAD_REQUEST).body(ex.getMessage()).build();
return request.createResponseBuilder(HttpStatus.OK).body("File uploaded successfully").build();
我的要求是通过 azure 函数将大文件上传到存储。任何帮助都将不胜感激。
【问题讨论】:
【参考方案1】:这似乎是因为您需要将原始流上传到 blob 存储。我以前用turn it to byte[]上传,但也失败了。我使用 C# 并遇到了与您相同的问题。 问题出在这个地方:
String body = request.getBody().get();
InputStream inputStream = new ByteArrayInputStream(body.getBytes());
blob.upload(inputStream, Integer.parseInt(bodyLength));
在 C# 中,我使用 blob.UploadFromStreamAsync(req.Body);
,然后问题就消失了。你可以检查Java是否有类似的方法。
【讨论】:
我们在 java 中有 blob.uploadFromByteArray(bytes,0,bytes.length)。但它没有用。【参考方案2】:经测试,是请求头引起的。从这个similar answer,您可以发现必须发送带有multipart/form-data
标头的正文。如果没有标题,我会得到和你一样的结果。
设置content-type
标头后,长度不变。
但是即使长度相等,如果您发送的文件不是txt文件而是pdf或图像等。Java Azure Function会出现一些字节丢失的问题,这将与OP更新中的情况相同我参考的答案。
所以如果你上传其他类型的文件,解决方法是将文件转换为base64字符串发布到Function,然后在函数中转换base64字符串然后上传到blob。
byte[] scanBytes = Base64.getDecoder().decode(base64 string from request);
blob.UploadFromByteArray(scanBytes , 0, scanBytes.Length);
节点:如果你想发布大文件,你应该知道有一个最大请求大小(100MB),这是无法更改的。 Github issue。但是在本地环境中最多声明是10MB~20MB,我测试本地出现这个限制。所以最好不要发布太大的文件。
【讨论】:
@user3407500,任何进程?你能用我的功能上传文件吗?如果这可以帮助你,请接受它作为答案。【参考方案3】:检查了the official tutorial,但遗憾的是,没有任何帮助。文档太旧了,甚至还有一些错误。
通过本地测试,我发现即使设置了正确的内容类型标头,azure java 函数也无法按预期处理不同的内容。
在大多数情况下,它会将内容视为纯文本。在大多数情况下,如果没有不可读的特殊字符,那将没有问题。
但是,对于其他文件,例如:图像文件、二进制文件和其他可能包含不可读特殊字符的文件,Azure 函数似乎只是忽略了一些不可读字符。
为了解决这个问题,您可以将请求内容类型标头设置为application/octet-stream
,这意味着它是未知格式。这样,Azure 函数将保留所有内容字节。
但是,George 的方式(使用 multipart/form-data)也可以。因为如果 content-type 是 multipart/form-data,系统也会保留所有的内容(这是诀窍),这样你就可以得到每个部分都有定义的边界字符串。该方法的使用场景是以http形式上传文件。您只需将 enctype 设置为“multipart/form-data”
<FORM method="POST" action="....." enctype="multipart/form-data">
<INPUT type="file" name="pic">
<INPUT type="submit" value="submit" name="submit">
</FORM>
因此,如果您只想通过编程将文件发布到 Azure 函数,请将 content-type 设置为 application/octet-stream。
【讨论】:
以上是关于使用java中的azure函数将文件从浏览器上传到azure blob存储的主要内容,如果未能解决你的问题,请参考以下文章
将文件从浏览器上传到 Azure Blob 存储,无需 SAS 密钥
如何从 azure 函数应用程序将文件发送到 azure 存储