5

On my HTTP server I'm trying to allow users to upload images by this form:

<form action="/?command=saveImage" method="post" enctype="multipart/form-data">
  <input type="file" name="images" multiple="multiple"/>
  <input type="submit">
</form>

I'm using this source to upload an image: http://embarcadero.newsgroups.archived.at/public.delphi.internet.winsock/201107/1107276163.html and changed ProcessMimePart procedure in order to save the images in their correct format:

procedure ProcessMimePart(var aDecoder: TIdMessageDecoder;
  var aMsgEnd: Boolean);
var
  LMStream: TMemoryStream;
  LNewDecoder: TIdMessageDecoder;
  fileName, fileExtension: string;
begin
  fileName := aDecoder.fileName;
  fileExtension := GetFileExtension(fileName);

  if (fileExtension <> 'jpg') and (fileExtension <> 'png') 
    and (fileExtension <> 'bmp') then
  begin
    Exit;
  end;

  LMStream := TMemoryStream.Create;
  try
    LNewDecoder := aDecoder.ReadBody(LMStream, aMsgEnd);
    try
      LMStream.Position := 0;
      TSaveImageController.WriteImage(fileName, fileExtension, LMStream);
    except
      LNewDecoder.Free;
      raise;
    end;
    aDecoder.Free;
    aDecoder := LNewDecoder;
  finally
    FreeAndNil(LMStream);
  end;
end;

This code works fine when I upload one file but when I try to upload more images I save the first image and the I get a: 'Access violation at address 004BAD86 in module 'App.exe'. Read of address 00000000'

EDIT:

function GetFileExtension(aFileName: string): string;
var
  isValidImageFileExtension: Boolean;
  lastIndexOfComa: integer;
  fileExtension: string;
begin
  lastIndexOfComa := aFileName.LastIndexOf('.');
  if lastIndexOfComa <= 0 then
  begin
    Result := '';
  end
  else
  begin
    fileExtension := LowerCase(aFileName.Substring(lastIndexOfComa + 1));
    if (fileExtension = 'jpg') or (fileExtension = 'bmp') or
      (fileExtension = 'png') then
    begin
      Result := fileExtension;
      Exit;
    end
    else
    begin
      Result := '';
    end;
  end;
end;
bob_saginowski
  • 1,429
  • 2
  • 20
  • 35
  • That means you are trying to access some object reference that is set to `nil`. Besides, the code you show is not all the code in the link you provide. Are you sure that the `aDecoder` parameter is not `nil` the second time you get into `ProcessMimePart`? – Guillem Vicens Sep 19 '14 at 12:34
  • @GuillemVicens the second time I get in the second repeat-until loop (check the link) the exception is thrown – bob_saginowski Sep 19 '14 at 12:44
  • It would help to know which line is actually raising the exception. I'm the one who wrote the code you linked to, and I tested it at the time I posted it, and it worked fine. I see nothing in your code that should be accessing a nil pointer. On a side note, your file extension check is wrong. You need to use `and` instead of `or`. – Remy Lebeau Sep 19 '14 at 16:00
  • @RemyLebeau just edited it. On this line of the source: LDecoder.ReadHeader; in the second repeat-until loop – bob_saginowski Sep 19 '14 at 16:06
  • 1
    What type of files are you uploading? One thing I just noticed is that if your file extension check exits, you are not calling `ReadBody()`, so the next loop iteration will be in the wrong position of the `PostStream` when `ReadHeader()` is called. You need to call `ReadBody()` on each iteration, even if you do not use the data. I would have to check if `ReadBody()` allows a nil target stream, or you could use `TIdEventStream`, to discard unwanted data so you don't waste memory on it. – Remy Lebeau Sep 19 '14 at 16:12
  • I'm uploading .jpg, .bmp, .png files. I call `ReadBody()` after I create the memory stream. – bob_saginowski Sep 19 '14 at 16:34
  • You are doing case-sensitive comparisons of the file extensions. Does your `GetFileExtension()` function (which is not an Indy or Embarcadero function) ensure that its output is always lowercase and without a leading period? Did you verify that when the problem does occur, `ReadBody()` was actually called and not skipped? Please make sure `ReadBody()` is NEVER skipped, or you will get out of sync. – Remy Lebeau Sep 24 '14 at 02:47
  • Also, which version of Indy are you using? Maybe you are simply using an older version that has some logic bugs in it. Hard to know since you never said which version you are using. It might also help if you could show what the raw `PostStream` data looks like before it is parsed, in case there is an error/oddity in the data itself. – Remy Lebeau Sep 24 '14 at 02:50
  • Which minor number? (Many years passed between 10.0 and 10.6). – mjn Sep 24 '14 at 12:52

0 Answers0