2

What's the equivalent of PHP's $_FILES variable in C#? Or at least something that accesses the files in the same way. I've got an upload form that I can't change and need to find out how to get at these files.

Rob
  • 45,296
  • 24
  • 122
  • 150
Brian Hicks
  • 6,213
  • 8
  • 51
  • 77

3 Answers3

9

Take a look at Request.Files, for example:

foreach (HttpPostedFile item in Request.Files)
{
    var filename = item.FileName;

    var fileBytes = new byte[item.ContentLength];
    item.InputStream.Read(fileBytes, 0, item.ContentLength);

    // fileBytes now contains the content of the file
    // filename contains the name of the file
}
Rob
  • 45,296
  • 24
  • 122
  • 150
  • 1
    Downvoted because the use of `Stream.Read()` is buggy: it might not read the entire content length. You would have to use a loop; or you could instantiate a `MemoryStream` and then use `item.InputStream.CopyTo()`. – Timwi Jul 30 '10 at 22:06
  • @Rob: because it might take some people slightly more than 21 seconds to write a meaningful, non-stupid comment. – Timwi Jul 30 '10 at 22:06
  • @Timwi, it's not buggy in the slightest, by the time you can access Request.Files, all the content is available for processing. I have code in production use that proves such.. – Rob Jul 30 '10 at 22:07
  • 1
    @Rob: Sorry, it is buggy. Read up on the contract for `Stream.Read()`. – Timwi Jul 30 '10 at 22:07
  • @Timwi, Stream.Read is an *abstract* method, ergo there's no implementation there to be buggy... – Rob Jul 30 '10 at 22:09
  • @Rob: If you read up on Stream.Read carefully you'll see that you CANNOT reliably read it in one go. It may return you just 1 byte even if there are more available. The fact that a specific use case works is a fluke and an implementation detail, which the implementor may choose to change. – Roman Starkov Jul 30 '10 at 22:12
  • @Rob: I said *contract*, not *implementation*. Since it is abstract, it is *particularly important* to know its contract before calling it. If you don’t know this, you shouldn’t be writing code that uses abstract methods, because you’ll be generating bugs. – Timwi Jul 30 '10 at 22:14
  • I take it you're alluding to "An implementation is free to return fewer bytes than requested even if the end of the stream has not been reached."? Whilst it might be "an implementation detail, which the implemtor may choose to change", I deem it reasonable to rely on the implementation of the .net framework that I'm targeting and its current behaviour. Yes, service packs have changed behaviours previously, but that's why testing occurs prior to the deployment of framework updates to production systems. – Rob Jul 30 '10 at 22:18
  • @Rob... there’s nothing wrong with making a mistake, even the best developers do. But a good developer can live up to a mistake and learn from it. You’re trying to reason it away and maintain your ego. Consequently, you will generate the same bug again in the future. – Timwi Jul 30 '10 at 22:27
  • 3
    Timwi, I'm sure you will apologize to Rob for your mistake. Unless you want to say that the documentation of HttpPostedFile.InputStream at http://msdn.microsoft.com/en-us/library/system.web.httppostedfile.inputstream.aspx is wrong to use the same example that Rob is using. Besides, if you bother to use Reflector to check HttpInputStream you will see that it contains the entire file contents in memory and returns all available bytes.In the end, both Save and Read will call the same GetBytes method, with the same arguments. Seems you need don't know streams as well as you thought – Panagiotis Kanavos Jul 30 '10 at 23:25
  • What you are suggesting is to *look at an internal implementation detail using Reflector* and then to go ahead and *write code that assumes this internal implementation*. This is called tight coupling and is a common source of hard-to-find bugs. Code contracts were invented to mitigate this. (And yes, I’m afraid the MSDN example has the same bug.) – Timwi Jul 30 '10 at 23:32
  • http://stackoverflow.com/questions/221925/creating-a-byte-array-from-a-stream for a correct way to read all bytes from a stream. Observe also a an answer with -6 votes that does it your way. – Roman Starkov Jul 30 '10 at 23:45
2

You will have an HttpRequest object passed in to your handler, right? Just access that object’s Files property:

for (int i = 0; i < request.Files.Count; i++)
{
    var file = request.Files[i];
    // Do something with this file, for example:
    file.SaveAs(Path.Combine(someDirectory, file.FileName));
}
Timwi
  • 65,159
  • 33
  • 165
  • 230
0

You can also use sometimes ( for example with uploadify ) the HttpPostedFileBase parameter:

Ex:

public ActionResult UploadPicture(HttpPostedFileBase fileData){
  img = Image.FromStream(fileData.InputStream, true, true);
}
danpop
  • 967
  • 13
  • 25