.NET中如何向Azure Function发送图片列表实现带元数据的Blob上传
带元数据的多图片批量上传实现方案
安卓端实现逻辑
直接采用 multipart/form-data 格式发起POST请求即可,无需手动处理流/字节数组的序列化逻辑,该格式天然支持同时传输二进制图片文件和文本类型的元数据,两端都有成熟的工具类库兼容,实现成本低且不易出错。
示例参考(基于OkHttp):
val okHttpClient = OkHttpClient() val multipartBuilder = MultipartBody.Builder().setType(MultipartBody.FORM) // 遍历待上传的图片列表,和对应的元数据列表一一对应 imageList.forEachIndexed { index, imageFile -> // 添加图片文件部分 multipartBuilder.addFormDataPart( "image_$index", imageFile.name, RequestBody.create("image/*".toMediaType(), imageFile) ) // 添加对应元数据部分:将元数据Map序列化为JSON字符串传输 val metadataJson = Gson().toJson(metadataList[index]) multipartBuilder.addFormDataPart("metadata_$index", null, RequestBody.create("text/plain".toMediaType(), metadataJson)) } // 构建请求,注意补充Function的访问密钥 val request = Request.Builder() .url("https://<你的Function域名>/api/product/uploadimages") .addHeader("x-functions-key", "<你的Function访问密钥>") .post(multipartBuilder.build()) .build() // 执行请求 okHttpClient.newCall(request).execute()
Azure Function 端实现逻辑
直接解析传入的multipart请求,按索引匹配图片和对应元数据后,复用你原有Blob上传+设置元数据的逻辑即可,完整代码示例:
using System.Net; using System.Net.Http; using System.Net.Http.Headers; using Azure.Storage.Blobs; using Newtonsoft.Json; [FunctionName("UploadProductImages")] public async Task<HttpResponseMessage> UploadProductImages( [HttpTrigger(AuthorizationLevel.Function, "post", Route = "product/uploadimages")] HttpRequestMessage req, Microsoft.Extensions.Logging.ILogger log) { try { // 初始化Blob容器客户端,建议通过依赖注入注入,这里仅做示例 var containerClient = new BlobClient("<你的Blob存储连接字符串>", "<你的容器名>"); // 解析Multipart请求 var multipartProvider = await req.Content.ReadAsMultipartAsync(); // 遍历所有待上传的图片,按索引匹配元数据 for (int i = 0; ; i++) { var imagePart = multipartProvider.Contents.FirstOrDefault(c => c.Headers.ContentDisposition.Name == $"\"image_{i}\""); if (imagePart == null) break; // 没有更多图片,结束遍历 // 读取文件名 var fileName = imagePart.Headers.ContentDisposition.FileName.Trim('"'); // 读取对应元数据 var metadataPart = multipartProvider.Contents.First(c => c.Headers.ContentDisposition.Name == $"\"metadata_{i}\""); var metadataStr = await metadataPart.ReadAsStringAsync(); var metadata = JsonConvert.DeserializeObject<Dictionary<string, string>>(metadataStr); // 上传图片到Blob存储 using var imageStream = await imagePart.ReadAsStreamAsync(); var blobClient = containerClient.GetBlobClient(fileName); await blobClient.UploadAsync(imageStream, overwrite: true); // 设置元数据,和你原有逻辑完全兼容 await blobClient.SetMetadataAsync(metadata); } return req.CreateResponse(HttpStatusCode.OK, "所有图片上传成功"); } catch (Exception ex) { log.LogError(ex, "图片上传失败"); return req.CreateErrorResponse(HttpStatusCode.InternalServerError, "上传失败:" + ex.Message); } }
额外优化建议
- 可以在请求中加入文件大小、格式校验,避免非法请求消耗资源
- 若有大图片上传需求,可以在安卓端实现分块上传,Function端对应做分片合并逻辑
- Blob存储的元数据Key有命名规范限制,不支持特殊字符,可以在Function中加入校验逻辑避免设置失败
内容的提问来源于stack exchange,提问作者Ronak Shetiya
相关产品推荐
相关产品推荐

