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

C#写入文件至S3后删除本地文件遇占用错误求助

问题描述

我编写的程序逻辑是从Web服务拉取数据写入CSV文件,接着把文件上传到Amazon S3,最后尝试删除本地文件时触发了错误:

System.IO.IOException: 'The process cannot access the file 'file.csv' because it is being used by another process.'

我猜测是S3上传未完成(文件还没出现在S3里)导致的问题,相关代码如下:

我原本的执行顺序是先关闭文件,再上传S3,最后删除:

outputFile.Flush(); 
outputFile.Close(); 
AmazonS3Uploader awsfu = new AmazonS3Uploader(); 
awsfu.UploadFile(outputfilePath, "api-end-point", filenameaws); 
System.IO.File.Delete(@outputfilePath); 

S3上传的代码实现:

class AmazonS3Uploader { 
    public void UploadFile(string filePath, string bucketName, string keyName) { 
        var client1 = new AmazonS3Client(Amazon.RegionEndpoint.USEast2); 
        Console.WriteLine("s3 writing"); 
        try { 
            PutObjectRequest Request = new PutObjectRequest { 
                BucketName = bucketName, 
                Key = keyName, 
                FilePath = filePath, 
            }; 
            client1.PutObjectAsync(Request); 
        } catch (AmazonS3Exception amazonS3Exception) { 
            if (amazonS3Exception.ErrorCode != null && (amazonS3Exception.ErrorCode.Equals("InvalidAccessKeyId") || amazonS3Exception.ErrorCode.Equals("InvalidSecurity"))) { 
                throw new Exception("Check the provided AWS Credentials."); 
            } else { 
                throw new Exception("Error occurred: " + amazonS3Exception.Message); 
            } 
        } 
        //System.IO.File.Delete(@filePath); edit 
    } 
} 

恳请各位提供解决建议。


解决建议

其实问题的核心不是上传没完成,而是你用了异步方法却没等待它执行完毕!PutObjectAsync是异步方法,调用它之后会立刻返回,程序直接走到删除文件的步骤,但这时候S3客户端还在后台读取这个文件,自然就会出现文件被占用的错误。

这里有几个可行的解决办法:

1. 等待异步上传完成(推荐)

把UploadFile方法改成异步方法,调用的时候用await等待上传完成:

首先修改AmazonS3Uploader的代码:

class AmazonS3Uploader { 
    // 改成异步方法,返回Task
    public async Task UploadFileAsync(string filePath, string bucketName, string keyName) { 
        var client1 = new AmazonS3Client(Amazon.RegionEndpoint.USEast2); 
        Console.WriteLine("s3 writing"); 
        try { 
            PutObjectRequest Request = new PutObjectRequest { 
                BucketName = bucketName, 
                Key = keyName, 
                FilePath = filePath, 
            }; 
            // 用await等待异步操作完成
            await client1.PutObjectAsync(Request); 
        } catch (AmazonS3Exception amazonS3Exception) { 
            if (amazonS3Exception.ErrorCode != null && (amazonS3Exception.ErrorCode.Equals("InvalidAccessKeyId") || amazonS3Exception.ErrorCode.Equals("InvalidSecurity"))) { 
                throw new Exception("Check the provided AWS Credentials."); 
            } else { 
                throw new Exception("Error occurred: " + amazonS3Exception.Message); 
            } 
        } 
    } 
} 

然后修改调用方的代码(注意调用方的方法也要改成异步,比如加上async关键字):

outputFile.Flush(); 
outputFile.Close(); 
AmazonS3Uploader awsfu = new AmazonS3Uploader(); 
// 用await等待上传完成
await awsfu.UploadFileAsync(outputfilePath, "api-end-point", filenameaws); 
System.IO.File.Delete(@outputfilePath); 

2. 改用同步上传方法

如果你不想用异步,也可以直接使用同步版本的PutObject方法,这样程序会等到上传完成后再执行删除:

修改UploadFile里的代码:

// 替换PutObjectAsync为PutObject
client1.PutObject(Request); 

这样调用的时候就不需要改异步相关的代码,程序会按顺序执行完上传再删除文件。

额外小提示

另外,建议你使用using语句来处理文件流,这样可以自动释放文件资源,避免手动Flush和Close可能出现的遗漏:

using (var outputFile = new StreamWriter(outputfilePath))
{
    // 写入数据的逻辑
}
// 这里文件已经自动被释放了

这样即使后续代码出问题,文件资源也能被正确释放,减少文件被占用的概率。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:24:51