将文件写入 .NET Core 中的临时文件夹后无法读取文件
Can't read file after writing it to temp folder in .NET Core
在我的场景中,我有一个用例,我必须接收一个压缩文件,进行一些验证,然后在存档中找到我必须通过第三方库处理的特定文件。不过,我在让这样的库读取文件时遇到了一些麻烦。这是我到目前为止想出的:
public async Task ShapeIt(ZipArchive archive)
{
foreach (var entry in archive.Entries)
{
if (Path.GetExtension(entry.FullName).Equals(".shp"))
{
var stream = entry.Open();
using var ms = new MemoryStream();
await stream.CopyToAsync(ms);
ms.Position = 0;
var fileName = Path.GetTempFileName();
try
{
using var fileStream = File.Open(fileName, FileMode.OpenOrCreate, FileAccess.Write,
FileShare.ReadWrite);
var bytes = new byte[ms.Length];
ms.Read(bytes, 0, (int)ms.Length);
fileStream.Write(bytes, 0, bytes.Length);
fileStream.Flush();
fileStream.Close();
var featureSource = new ShapeFileFeatureSource(fileName); // Class from 3rd-party
featureSource.Open();
// Do my stuff with the shapefile
}
finally
{
File.Delete(fileName);
}
}
}
}
请注意,我正在使用 "old way" 复制流,因为 Stream.CopyTo
和 Stream.CopyToAsync
正在创建空文件,显式调用 fileStream.Close()
看起来是唯一的方法以某种方式将字节放入文件中,但这超出了我的观点。无论如何,在 关闭流 之后,调用 featureSource.Open()
我的应用程序抛出
"The process cannot access the file 'C:\Users\me\AppData\Local\Temp\tmpE926.tmp' because it is
being used by another process."
tmpE926.tmp
显然每次都不一样。另请注意,我正在创建一个文件,因为 ShapeFileFeatureSource
的构造函数不需要流、字节数组,而是路径。
更短的实现
public async Task ShapeIt(ZipArchive archive)
{
foreach (var entry in archive.Entries)
{
var tempFile = Path.GetTempFileName();
try
{
entry.ExtractToFile(tempFile, true);
if (Path.GetExtension(entry.FullName).Equals(".shp"))
{
var featureSource = new ShapeFileFeatureSource(tempFile);
featureSource.Open();
var type = featureSource.GetShapeFileType();
}
}
finally
{
File.Delete(tempFile);
}
}
}
实际上会产生相同的错误。老实说,我不认为问题出在这个库中,而是我以某种方式把它搞砸了。有没有人有任何想法或者我应该联系供应商的(无响应的)技术支持?
编辑:以防万一,这就是这样的库 Install-Package ThinkGeo.UI.WebApi
但您必须订阅才能评估才能使用它。
我找不到这样的 .NET Core 包 类,所以我通过 .NET Framework Nuget 包复制了它。我的回答主要是演示如何处理流。如果无法访问您拥有的库,很难判断您的代码有什么问题
using DotSpatial.Data;
using System.IO;
using System.IO.Compression;
namespace ConsoleApp12
{
class Program
{
static void Main(string[] args)
{
using (var fs = File.OpenRead(@"C:\Users\jjjjjjjjjjjj\Downloads70055001_mb_2011_vic_shape.zip"))
using (var zipFile = new ZipArchive(fs))
{
foreach (var entry in zipFile.Entries)
{
if (entry.FullName.EndsWith(".shp"))
{
var tempFile = Path.GetTempFileName();
try
{
using (var entryStream = entry.Open())
using (var newFileStream = File.OpenWrite(tempFile))
{
entryStream.CopyTo(newFileStream);
}
var featureSource = ShapefileFeatureSource.Open(tempFile);
var type = featureSource.ShapeType;
}
finally
{
File.Delete(tempFile);
}
}
}
}
}
}
}
UPD:安装了 ThinkGeo 库的试用版,而不是未经授权的异常,它给了我 FileNotFoundException
和给定的堆栈跟踪
at ThinkGeo.Core.ValidatorHelper.CheckFileIsExist(String pathFilename)
at ThinkGeo.Core.ShapeFileIndex.xh8=(FileAccess readWriteMode)
^^^^^^^^^^^^^^^^^^^^^^^^^ Are we supposed to have index?
at ThinkGeo.Core.ShapeFile.xh8=(FileAccess readWriteMode)
at ThinkGeo.Core.ShapeFileFeatureSource.WjE=()
at ThinkGeo.Core.ShapeFileFeatureSource.OpenCore()
at ThinkGeo.Core.FeatureSource.Open()
at ConsoleApp20.Program.Main(String[] args) in
C:\Users\jjjjjjjjjjjj\source\repos\ConsoleApp20\ConsoleApp20\Program.cs:line 45
ShapeFileIndex
?所以我想我应该以这种方式深入研究
var featureSource = new ShapeFileFeatureSource(tempFile);
featureSource.RequireIndex = false; // no luck
featureSource.Open();
我试图找到它想要的任何对 idx 文件的引用,它有 属性 IndexFilePathName
,但不幸的是,我运气不好。 (也尝试了不同的文件夹,所以这不是 'Temp' 文件夹问题)
这段代码变形了几天,直到我联系到技术支持,他们稍微修改了一下,想出了这个:
public async Task ProcessFile(IFormFile file)
{
if (!Path.GetExtension(file.FileName).Equals(".zip"))
throw new System.Exception("File should be compressed in '.zip' format");
var filePaths = new List<string>();
using (var stream = new MemoryStream())
{
await file.CopyToAsync(stream);
using (var archive = new ZipArchive(stream, ZipArchiveMode.Read, false))
{
var replaceList = new Dictionary<string, string>();
foreach (ZipArchiveEntry entry in archive.Entries)
{
var tempPath = Path.GetTempFileName();
string key = Path.GetFileNameWithoutExtension(entry.FullName);
string value = Path.GetFileNameWithoutExtension(tempPath);
if (replaceList.ContainsKey(key))
{
value = replaceList[key];
}
else
{
replaceList.Add(key, value);
}
string unzippedPath = Path.Combine(Path.GetDirectoryName(tempPath), value + Path.GetExtension(entry.FullName));
entry.ExtractToFile(unzippedPath, true);
filePaths.Add(unzippedPath);
}
foreach (var unzippedPath in filePaths)
{
if (Path.GetExtension(unzippedPath).Equals(".shp"))
{
// Successfully doing third-party library stuff
}
}
foreach (var unzippedPath in filePaths)
{
if (File.Exists(unzippedPath))
{
File.Delete(unzippedPath);
}
}
}
}
}
有效。我很开心。
在我的场景中,我有一个用例,我必须接收一个压缩文件,进行一些验证,然后在存档中找到我必须通过第三方库处理的特定文件。不过,我在让这样的库读取文件时遇到了一些麻烦。这是我到目前为止想出的:
public async Task ShapeIt(ZipArchive archive)
{
foreach (var entry in archive.Entries)
{
if (Path.GetExtension(entry.FullName).Equals(".shp"))
{
var stream = entry.Open();
using var ms = new MemoryStream();
await stream.CopyToAsync(ms);
ms.Position = 0;
var fileName = Path.GetTempFileName();
try
{
using var fileStream = File.Open(fileName, FileMode.OpenOrCreate, FileAccess.Write,
FileShare.ReadWrite);
var bytes = new byte[ms.Length];
ms.Read(bytes, 0, (int)ms.Length);
fileStream.Write(bytes, 0, bytes.Length);
fileStream.Flush();
fileStream.Close();
var featureSource = new ShapeFileFeatureSource(fileName); // Class from 3rd-party
featureSource.Open();
// Do my stuff with the shapefile
}
finally
{
File.Delete(fileName);
}
}
}
}
请注意,我正在使用 "old way" 复制流,因为 Stream.CopyTo
和 Stream.CopyToAsync
正在创建空文件,显式调用 fileStream.Close()
看起来是唯一的方法以某种方式将字节放入文件中,但这超出了我的观点。无论如何,在 关闭流 之后,调用 featureSource.Open()
我的应用程序抛出
"The process cannot access the file 'C:\Users\me\AppData\Local\Temp\tmpE926.tmp' because it is
being used by another process."
tmpE926.tmp
显然每次都不一样。另请注意,我正在创建一个文件,因为 ShapeFileFeatureSource
的构造函数不需要流、字节数组,而是路径。
更短的实现
public async Task ShapeIt(ZipArchive archive)
{
foreach (var entry in archive.Entries)
{
var tempFile = Path.GetTempFileName();
try
{
entry.ExtractToFile(tempFile, true);
if (Path.GetExtension(entry.FullName).Equals(".shp"))
{
var featureSource = new ShapeFileFeatureSource(tempFile);
featureSource.Open();
var type = featureSource.GetShapeFileType();
}
}
finally
{
File.Delete(tempFile);
}
}
}
实际上会产生相同的错误。老实说,我不认为问题出在这个库中,而是我以某种方式把它搞砸了。有没有人有任何想法或者我应该联系供应商的(无响应的)技术支持?
编辑:以防万一,这就是这样的库 Install-Package ThinkGeo.UI.WebApi
但您必须订阅才能评估才能使用它。
我找不到这样的 .NET Core 包 类,所以我通过 .NET Framework Nuget 包复制了它。我的回答主要是演示如何处理流。如果无法访问您拥有的库,很难判断您的代码有什么问题
using DotSpatial.Data;
using System.IO;
using System.IO.Compression;
namespace ConsoleApp12
{
class Program
{
static void Main(string[] args)
{
using (var fs = File.OpenRead(@"C:\Users\jjjjjjjjjjjj\Downloads70055001_mb_2011_vic_shape.zip"))
using (var zipFile = new ZipArchive(fs))
{
foreach (var entry in zipFile.Entries)
{
if (entry.FullName.EndsWith(".shp"))
{
var tempFile = Path.GetTempFileName();
try
{
using (var entryStream = entry.Open())
using (var newFileStream = File.OpenWrite(tempFile))
{
entryStream.CopyTo(newFileStream);
}
var featureSource = ShapefileFeatureSource.Open(tempFile);
var type = featureSource.ShapeType;
}
finally
{
File.Delete(tempFile);
}
}
}
}
}
}
}
UPD:安装了 ThinkGeo 库的试用版,而不是未经授权的异常,它给了我 FileNotFoundException
和给定的堆栈跟踪
at ThinkGeo.Core.ValidatorHelper.CheckFileIsExist(String pathFilename)
at ThinkGeo.Core.ShapeFileIndex.xh8=(FileAccess readWriteMode)
^^^^^^^^^^^^^^^^^^^^^^^^^ Are we supposed to have index?
at ThinkGeo.Core.ShapeFile.xh8=(FileAccess readWriteMode)
at ThinkGeo.Core.ShapeFileFeatureSource.WjE=()
at ThinkGeo.Core.ShapeFileFeatureSource.OpenCore()
at ThinkGeo.Core.FeatureSource.Open()
at ConsoleApp20.Program.Main(String[] args) in
C:\Users\jjjjjjjjjjjj\source\repos\ConsoleApp20\ConsoleApp20\Program.cs:line 45
ShapeFileIndex
?所以我想我应该以这种方式深入研究
var featureSource = new ShapeFileFeatureSource(tempFile);
featureSource.RequireIndex = false; // no luck
featureSource.Open();
我试图找到它想要的任何对 idx 文件的引用,它有 属性 IndexFilePathName
,但不幸的是,我运气不好。 (也尝试了不同的文件夹,所以这不是 'Temp' 文件夹问题)
这段代码变形了几天,直到我联系到技术支持,他们稍微修改了一下,想出了这个:
public async Task ProcessFile(IFormFile file)
{
if (!Path.GetExtension(file.FileName).Equals(".zip"))
throw new System.Exception("File should be compressed in '.zip' format");
var filePaths = new List<string>();
using (var stream = new MemoryStream())
{
await file.CopyToAsync(stream);
using (var archive = new ZipArchive(stream, ZipArchiveMode.Read, false))
{
var replaceList = new Dictionary<string, string>();
foreach (ZipArchiveEntry entry in archive.Entries)
{
var tempPath = Path.GetTempFileName();
string key = Path.GetFileNameWithoutExtension(entry.FullName);
string value = Path.GetFileNameWithoutExtension(tempPath);
if (replaceList.ContainsKey(key))
{
value = replaceList[key];
}
else
{
replaceList.Add(key, value);
}
string unzippedPath = Path.Combine(Path.GetDirectoryName(tempPath), value + Path.GetExtension(entry.FullName));
entry.ExtractToFile(unzippedPath, true);
filePaths.Add(unzippedPath);
}
foreach (var unzippedPath in filePaths)
{
if (Path.GetExtension(unzippedPath).Equals(".shp"))
{
// Successfully doing third-party library stuff
}
}
foreach (var unzippedPath in filePaths)
{
if (File.Exists(unzippedPath))
{
File.Delete(unzippedPath);
}
}
}
}
}
有效。我很开心。