如何实例化一个HttpPostedFile

15
我想要和一个我无法控制的系统进行通信,但其中一个方法需要传入一个 HttpPostedFile,而我代码中只有一个字节数组。请问有没有人能提供一个实例化 HttpPostedFile 的示例,因为我知道它的构造函数是 internal 的。
目前我找到的最好的方法是使用反射创建 HttpPostedFile 的示例,可以参考 Creating an instance of HttpPostedFile with Reflection,但由于我无法修改第三方系统的方法签名,所以我不能采用其中的建议。
2个回答

27

以下代码有点“hacky”,但是似乎对我有效:

public HttpPostedFile ConstructHttpPostedFile(byte[] data, string filename, string contentType) {
  // Get the System.Web assembly reference
  Assembly systemWebAssembly = typeof (HttpPostedFileBase).Assembly;
  // Get the types of the two internal types we need
  Type typeHttpRawUploadedContent = systemWebAssembly.GetType("System.Web.HttpRawUploadedContent");
  Type typeHttpInputStream = systemWebAssembly.GetType("System.Web.HttpInputStream");

  // Prepare the signatures of the constructors we want.
  Type[] uploadedParams = { typeof(int), typeof(int) };
  Type[] streamParams = {typeHttpRawUploadedContent, typeof (int), typeof (int)};
  Type[] parameters = { typeof(string), typeof(string), typeHttpInputStream };

  // Create an HttpRawUploadedContent instance
  object uploadedContent = typeHttpRawUploadedContent
    .GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, uploadedParams, null)
    .Invoke(new object[]{data.Length, data.Length});

  // Call the AddBytes method
  typeHttpRawUploadedContent
    .GetMethod("AddBytes", BindingFlags.NonPublic | BindingFlags.Instance)
    .Invoke(uploadedContent, new object[] {data, 0, data.Length});

  // This is necessary if you will be using the returned content (ie to Save)
  typeHttpRawUploadedContent
    .GetMethod("DoneAddingBytes", BindingFlags.NonPublic | BindingFlags.Instance)
    .Invoke(uploadedContent, null);

  // Create an HttpInputStream instance
  object stream = (Stream)typeHttpInputStream
    .GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, streamParams, null)
    .Invoke(new object[] {uploadedContent, 0, data.Length});

  // Create an HttpPostedFile instance
  HttpPostedFile postedFile = (HttpPostedFile)typeof(HttpPostedFile)
    .GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, parameters, null)
    .Invoke(new object[] {filename, contentType, stream});

  return postedFile;
}

@paracycle - 当调用返回的HttpPostedFile的.Save(filePath)时,我得到了一张空白图片。你有什么想法吗? - ajwaka
@wilsjd: 自从上次我看了这个以来已经过了太长时间。自那时起,.NET平台的代码可能已经发生了很大的变化。我建议你通过反编译工具(如Reflector)查看新代码,并进行适当的更改。 - paracycle
1
如果您需要保存HttpPostedFile,还需要调用DoneAddingBytes方法: typeHttpRawUploadedContent.GetMethod("DoneAddingBytes", BindingFlags.NonPublic | BindingFlags.Instance).Invoke(uploadedContent, null); - sundog
@sundog 谢谢,已经使用你的代码更新了示例。 - paracycle
1
这对于单元测试非常有用,为我节省了大量时间! - Adriano Carneiro
太棒了。已移植到VB.NET: - Gabriel Kniznik

7

你可以尝试

 var constructorInfo = typeof(HttpPostedFile).GetConstructors(BindingFlags.NonPublic | BindingFlags.Instance)[0];
 var obj = (HttpPostedFile)constructorInfo
           .Invoke(new object[] { "filename", "image/jpeg", null });

obj 是一个 HttpPostedFile 类型。我将最后一个参数设置为 null,但实际上应该是 HttpInputStream


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接