如何不先保存到磁盘,直接上传内存中的System.Drawing.Bitmap对象?
实现方案
完全可以做到无需保存到磁盘的内存直传,核心思路是把Bitmap对象直接序列化到内存流中,上传内存里的二进制数据即可,既省去了不必要的磁盘IO开销,也能避免临时文件权限不足、删除失败等异常问题。
适配原有WebClient的实现
如果你的服务端直接读取POST请求体的二进制内容,直接替换原有代码即可:
System.Drawing.Bitmap bmp = new Bitmap(someX, someY); // 你的图片生成逻辑 using (System.IO.MemoryStream ms = new System.IO.MemoryStream()) { // 将图片写入内存流,不落地磁盘 bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg); // 重置流指针到起始位置,避免读取为空 ms.Position = 0; using (System.Net.WebClient webClient = new System.Net.WebClient()) { // 直接上传内存流的字节数据 webClient.UploadData(urlToUploadTo, "POST", ms.ToArray()); } } // 释放GDI资源,避免内存泄漏 bmp.Dispose();
表单上传场景实现(模拟网页文件上传)
如果服务端要求multipart/form-data格式的表单提交(和网页选择文件上传的格式一致),更推荐使用官方更推荐的HttpClient实现,示例如下:
// 注意:HttpClient建议全局单例初始化,不要每次请求都新建实例 private static readonly System.Net.Http.HttpClient _httpClient = new System.Net.Http.HttpClient(); public async System.Threading.Tasks.Task UploadImageAsync(System.Drawing.Bitmap bmp, string uploadUrl, string formFieldName = "file", string fileName = "image.jpeg") { using (System.IO.MemoryStream ms = new System.IO.MemoryStream()) { bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg); ms.Position = 0; using (var content = new System.Net.Http.MultipartFormDataContent()) { var streamContent = new System.Net.Http.StreamContent(ms); streamContent.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("image/jpeg"); // formFieldName需要和服务端接收文件的表单字段名保持一致 content.Add(streamContent, formFieldName, fileName); var response = await _httpClient.PostAsync(uploadUrl, content); // 校验请求是否成功 response.EnsureSuccessStatusCode(); } } bmp.Dispose(); }
注意事项
System.Drawing.Bitmap属于GDI资源,使用完成后必须调用Dispose释放,或者嵌套在using代码块中,避免出现内存泄漏- 如需上传PNG等其他格式的图片,修改
ImageFormat的对应参数即可 - 内存流会在
using代码块结束后自动释放,无需手动处理
内容的提问来源于stack exchange,提问作者Darren
相关产品推荐
相关产品推荐

