You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 18:54:02