在文件流或字节数组中更改文件名以通过 WebAPI 发送
Changing the name of a file while in a filestream or byte array to send via WebAPI
我想获取文件的内容并在内存中重命名文件,以便使用 API 以不同的文件名发送。
目标:
- 不以任何方式改变原始文件(磁盘上的文件)。
- 不创建其他文件(例如使用新名称的文件副本)。我正在努力保持尽可能低的 IO 访问并在内存中执行所有操作。
- 将文件对象(在内存中)的名称更改为不同的名称。
- 将文件对象上传到另一台机器上的 WebAPI。
- 在源 MachineA 上有“FileA.txt”,在目标 MachineB 上有“FileB.txt”。
我认为这无关紧要,但我没有计划用新名称将文件写回系统(MachineA),它只会用于将文件对象(在内存中)发送到 MachineB通过网络 API.
我找到了一个使用反射来完成这个的解决方案...
FileStream fs = new FileStream(@"C:\myfile.txt", FileMode.Open);
var myField = fs.GetType()
.GetField("_fileName", BindingFlags.Instance | BindingFlags.NonPublic)
myField.SetValue(fs, "my_new_filename.txt");
但是,自从给出该解决方案以来已经有几年了。 2021 年有更好的方法吗?
另一种方法是在将文件保存在 MachineB 上时定义文件名。
您可以通过 Web API 将此文件名作为有效负载传递,并将其用作文件名。
//buffer as byte[] and fileName as string would come from the request
using (FileStream fs = new FileStream(fileName, FileMode.Create))
{
fs.Write(buffer, 0, buffer.Length);
}
我能想出的最好方法是使用我多年前的旧方法。下面展示了我是如何使用它的。我这样做只是为了屏蔽我发送到的第三方 WebAPI 的原始文件名。
// filePath: c:\test\my_secret_filename.txt
private byte[] GetBytesWithNewFileName(string filePath)
{
byte[] file = null;
using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
{
// Change the name of the file in memory (does not affect the original file)
var fileNameField = fs.GetType().GetField(
"_fileName",
BindingFlags.Instance | BindingFlags.NonPublic
);
// If I leave out the next line, the file name field will have the full filePath
// string as its value in the resulting byte array. This will replace that with
// only the file name I wish to pass along "my_masked_filename.txt".
fileNameField.SetValue(fs, "my_masked_filename.txt");
// Get the filesize of the file and make sure it's compatible with
// the binaryreader object to be used
int fileSize;
try { fileSize = Convert.ToInt32(fs.Length); }
catch(OverflowException)
{ throw new Exception("The file is to big to convert using a binary reader."); }
// Get the file into a byte array
using (var br = new BinaryReader(fs)) { file = br.ReadBytes(fileSize); }
}
return file;
}
我想获取文件的内容并在内存中重命名文件,以便使用 API 以不同的文件名发送。
目标:
- 不以任何方式改变原始文件(磁盘上的文件)。
- 不创建其他文件(例如使用新名称的文件副本)。我正在努力保持尽可能低的 IO 访问并在内存中执行所有操作。
- 将文件对象(在内存中)的名称更改为不同的名称。
- 将文件对象上传到另一台机器上的 WebAPI。
- 在源 MachineA 上有“FileA.txt”,在目标 MachineB 上有“FileB.txt”。
我认为这无关紧要,但我没有计划用新名称将文件写回系统(MachineA),它只会用于将文件对象(在内存中)发送到 MachineB通过网络 API.
我找到了一个使用反射来完成这个的解决方案...
FileStream fs = new FileStream(@"C:\myfile.txt", FileMode.Open);
var myField = fs.GetType()
.GetField("_fileName", BindingFlags.Instance | BindingFlags.NonPublic)
myField.SetValue(fs, "my_new_filename.txt");
但是,自从给出该解决方案以来已经有几年了。 2021 年有更好的方法吗?
另一种方法是在将文件保存在 MachineB 上时定义文件名。 您可以通过 Web API 将此文件名作为有效负载传递,并将其用作文件名。
//buffer as byte[] and fileName as string would come from the request
using (FileStream fs = new FileStream(fileName, FileMode.Create))
{
fs.Write(buffer, 0, buffer.Length);
}
我能想出的最好方法是使用我多年前的旧方法。下面展示了我是如何使用它的。我这样做只是为了屏蔽我发送到的第三方 WebAPI 的原始文件名。
// filePath: c:\test\my_secret_filename.txt
private byte[] GetBytesWithNewFileName(string filePath)
{
byte[] file = null;
using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
{
// Change the name of the file in memory (does not affect the original file)
var fileNameField = fs.GetType().GetField(
"_fileName",
BindingFlags.Instance | BindingFlags.NonPublic
);
// If I leave out the next line, the file name field will have the full filePath
// string as its value in the resulting byte array. This will replace that with
// only the file name I wish to pass along "my_masked_filename.txt".
fileNameField.SetValue(fs, "my_masked_filename.txt");
// Get the filesize of the file and make sure it's compatible with
// the binaryreader object to be used
int fileSize;
try { fileSize = Convert.ToInt32(fs.Length); }
catch(OverflowException)
{ throw new Exception("The file is to big to convert using a binary reader."); }
// Get the file into a byte array
using (var br = new BinaryReader(fs)) { file = br.ReadBytes(fileSize); }
}
return file;
}