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

如何通过WebJob每日将SharePoint Online库中图片保存至内网远程服务器?

实现方案

一、获取SharePoint Online文档库中的图片

要读取SharePoint Online的图片,推荐用Microsoft Graph API,步骤如下:

  • 先在Azure AD注册应用,拿到客户端ID、客户端密钥、租户ID,给应用分配Sites.Read.All权限(需要管理员同意)
  • 用Microsoft Graph SDK编写代码,遍历文档库里的图片文件,获取文件流(比Base64更高效)

示例代码片段:

using Microsoft.Graph;
using Azure.Identity;

var scopes = new[] { "https://graph.microsoft.com/.default" };
var tenantId = "你的租户ID";
var clientId = "你的客户端ID";
var clientSecret = "你的客户端密钥";
var siteId = "你的站点ID";
var driveId = "文档库ID";

var credential = new ClientSecretCredential(tenantId, clientId, clientSecret);
var graphClient = new GraphServiceClient(credential, scopes);

// 过滤出文档库中的图片文件
var imageItems = await graphClient.Sites[siteId].Drives[driveId].Root.Children
    .Request()
    .Filter("file ne null and file/mimeType starts with 'image/'")
    .GetAsync();

二、保存图片到内网非SFTP服务器

你的现有代码是存到SMB共享路径(\\remote server\share\temp\),如果目标服务器也是SMB共享,直接复用逻辑即可,优化下路径拼接和去重:

static string saveFolder = @"\\remote server\share\temp\";

public static void SaveImageFromStream(Stream imageStream, string fileName)
{
    try
    {
        // 去掉原文件后缀,统一存为jpg
        var baseName = Path.GetFileNameWithoutExtension(fileName);
        var savePath = Path.Combine(saveFolder, $"{baseName}.jpg");
        
        // 避免覆盖已存在文件,加时间戳
        if (File.Exists(savePath))
        {
            savePath = Path.Combine(saveFolder, $"{baseName}_{DateTime.Now:yyyyMMddHHmmss}.jpg");
        }

        using (Image image = Image.FromStream(imageStream))
        {
            image.Save(savePath);
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine($"保存图片失败:{ex.ToString()}");
    }
}

注意:运行程序的账号必须有该SMB共享的读写权限,否则会报错。

三、实现每日定时运行

推荐用Windows任务计划程序,简单适配内网环境:

  • 把代码编译成控制台.exe文件
  • 打开Windows任务计划程序,新建基本任务:
    • 设置触发条件为「每日」,指定运行时间
    • 操作选择「启动程序」,选中你的.exe文件
    • 配置运行账号,勾选「不管用户是否登录都要运行」,确保后台自动执行

如果有服务器上的.NET Web应用,也可以用Hangfire来配置定时任务;有Azure环境的话,也能创建定时触发的Azure Function(前提是Azure能打通内网)。

四、完整整合代码

把上述逻辑整合起来,完整的控制台程序示例:

using Microsoft.Graph;
using Azure.Identity;
using System.Drawing;
using System.IO;

class Program
{
    static string saveFolder = @"\\remote server\share\temp\";

    static async Task Main(string[] args)
    {
        var scopes = new[] { "https://graph.microsoft.com/.default" };
        var tenantId = "你的租户ID";
        var clientId = "你的客户端ID";
        var clientSecret = "你的客户端密钥";
        var siteId = "你的站点ID";
        var driveId = "文档库ID";

        try
        {
            var credential = new ClientSecretCredential(tenantId, clientId, clientSecret);
            var graphClient = new GraphServiceClient(credential, scopes);

            var imageItems = await graphClient.Sites[siteId].Drives[driveId].Root.Children
                .Request()
                .Filter("file ne null and file/mimeType starts with 'image/'")
                .GetAsync();

            foreach (var item in imageItems)
            {
                var fileStream = await graphClient.Sites[siteId].Drives[driveId].Items[item.Id].Content.Request().GetAsync();
                SaveImageFromStream(fileStream, item.Name);
            }

            Console.WriteLine("所有图片已保存完成");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"执行出错:{ex.ToString()}");
        }
    }

    public static void SaveImageFromStream(Stream imageStream, string fileName)
    {
        try
        {
            var baseName = Path.GetFileNameWithoutExtension(fileName);
            var savePath = Path.Combine(saveFolder, $"{baseName}.jpg");
            
            if (File.Exists(savePath))
            {
                savePath = Path.Combine(saveFolder, $"{baseName}_{DateTime.Now:yyyyMMddHHmmss}.jpg");
            }

            using (Image image = Image.FromStream(imageStream))
            {
                image.Save(savePath);
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"保存图片【{fileName}】失败:{ex.ToString()}");
        }
    }
}

关键注意事项

  • 权限:运行程序的账号要同时拥有SharePoint文档库的读取权限、内网共享文件夹的写入权限
  • 日志:可以把异常信息写入本地日志文件,方便后续排查问题
  • 依赖:需要安装NuGet包:Microsoft.Graph、Azure.Identity、System.Drawing.Common(注意.NET版本兼容性)
  • 去重优化:如果不想重复保存相同图片,可以对比文件的哈希值或修改时间,只同步新增/更新的图片

内容的提问来源于stack exchange,提问作者Kumbhar Kanchan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 21:18:21