3

Am uploading a file (any format doc, docx, pdf, text, etc) as multipart form/data to a REST API from Postman or application UI. The text file uploads fine. All other non-text formats get corrupted. I cant open those files.

The size of the uploaded file increases drastically. Check the following server log:

File size just before call to request.getRequestDispatcher().forward(): 27583
Controller, first line in method:39439

The size of the uploaded file is 27.3Kb

I am guessing the files gets corrupted because of the other data appended to the file.

Controller method is

@RequestMapping(value="/entity/{entity}/{entityId}/type/{type}/{derive}",method = RequestMethod.POST)
    @ResponseBody
    public String uploadFile(@RequestParam("file") MultipartFile multipartFile,@PathVariable("entity")String entity,@PathVariable("type")String type,@PathVariable("entityId")Long entityId,@PathVariable("derive") boolean derive) throws Exception

Since text file is saving correctly and other files also get written correctly, don't think the code to write the file is incorrect.

Code to get inputStream

public String storeFile(MultipartFile multipartFile, String entity, Long id, String uploadType, boolean isDerive,String customName)
                                                                                                                     throws Exception
    {
        try
        {
            System.out.println(multipartFile.getSize());
            String fileName = "";
            String contentType = "";
            if (multipartFile != null)
            {
                fileName = multipartFile.getOriginalFilename();
                contentType = multipartFile.getContentType();
                if (contentType == null)
                {
                    contentType = "application/msword";
                }
            }
            InputStream is = multipartFile.getInputStream();
            String filePath = getFileName(entity, uploadType, id, fileName, isDerive,customName);
            Helper.storeFile(is, filePath);
            precedingPath = precedingPath.length() > 0 ? precedingPath + "/":"";
            return precedingPath + filePath;
        }
        catch (WebException e)
        {
            e.printStackTrace();
            throw e;
        }
        catch (Exception e)
        {
            e.printStackTrace();
            throw new WebException(e.getMessage(), IHttpConstants.INTERNAL_SERVER_ERROR, e);
        }
    }

Helper.storeFile

public static File storeFile(InputStream is, String filePath) throws IOException {
        try {
            String staticRepoPath = null;

            if (MasterData.getInstance().getSettingsMap().containsKey(Settings.REPO_LOCATION.toString())) {
                staticRepoPath = MasterData.getInstance().getSettingsMap().get(Settings.REPO_LOCATION.toString());
            } else {
                throw new WebException("Invalid Settings");
            }

            byte[] buffer = new byte[is.available()];
            is.read(buffer);

            File targetFile = new File(staticRepoPath + File.separator + filePath);
            @SuppressWarnings("resource")
            OutputStream outStream = new FileOutputStream(targetFile);
            outStream.write(buffer);
            return targetFile;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

My Ajax request is as follows

var fd = new FormData();
//Take the first selected file
fd.append("file", document.actualFile);
//Generic AJAX call
CandidateService.ajax_uploadDocumentWithDocType($scope.candidate.id, fd, document.docType, function (error, json)

Content type while uploading:

 var config = {headers:{'X-Auth-Token':authToken, 'Content-Type': undefined}, transformRequest: angular.identity};

Would anyone know how I can fix this and upload the file successfully?

Q1) Why does the file size change between the request dispatcher and the controller that handles the file data.

Q2) Could this change of file size be the cause of file corruption? Libre Office cause General Input/Output Error.

4
  • Don't know why someone marked -1. I have been using this api for over a 1 year now. Since last 3 months the files get corrupted on upload. Have thoroughly checked my code via git history. Cannot figure out what changed. Hence went deeper to checking the file size etc. API call updated above Commented Jan 30, 2017 at 5:50
  • Have you tried with other APIs? Commented Jan 30, 2017 at 6:09
  • I didn't downvote, but you didn't post the code. No way to tell what you're doing with that MultipartFile. Commented Jan 30, 2017 at 6:38
  • Have added my code. user1478061: What other APIs? This REST API works for text files. The other binary files also get uploaded. But I cannot open the uploaded files. It gives General Input/Output error in Libre Office. The pdfs also dont open. I dont do anything else between the Spring request dispatcher to the controller call. Commented Jan 30, 2017 at 8:08

3 Answers 3

5

I figured the problem with the file upload. I had a spring filter in between that was changing the request to a wrappedRequest. This was adding additional data to the multipart data and causing the file to be corrupted.

Sign up to request clarification or add additional context in comments.

7 Comments

do you have more information by any chance? We encounter the same issue in a basic springboot app.
No. Dont have more information. The spring filters which run before the controller is called had caused the issue for us.
Sonal, could you please explain what changes you did in your controller or filter to solve this issue, I am also having exact same problem and using security filters.
Confirmed springSecurityFilterChain was corrupting the multipart files only in case of docx, pdf, removing them solves the issue. authorization filter doesn't causes any issue, wasted almost 2 days to find this solution
@Sonal, Thanks for sharing the idea, I was having the same problem and struggling with damaged file since last 2-3 days. Your idea helped me a lot. Thanks :)
|
1

Simplified Working Solution: 2024 & beyond:

It is weird but here is the solution:

Remove the enctype="multipart/form-data" from HTML form section.

In Javascript POST call, update the code as below:

fetch("http://example.com/path/upload.php", {
                method: 'PUT',
                body: event.target.files[0],
                headers: {
                'Content-Type': (event.target.files[0]).type
                }
            })

If you have formdata, remove it (these lines were responsible for corruption and unintended file size increases):

// const formData = new FormData();
// formData.append('file', file);

Summary:

  1. We remove unwanted enctype
  2. We remove formData which might add "webkit-boundary" garbage text to uploaded file.
  3. We pass the file data event.target.files[0] directly in Fetch/HTTP API's body param and set file-type/content-type properly from (event.target.files[0]).type
  4. Some other posts suggest setting 'Content-Type': undefined which may be incorrect and it didn't work out for us.
  5. Now the uploaded file is corruption-free; mainly .xlsx or .ppt or other complex file formats are uploaded successfully.

Notes: I'm co-dev at TimeOnSite for web.

1 Comment

This is very sensible and straight-forward answer for this file corruption issues. Removed FormData() and passed the event.file direclty in Angular this.http's body directly and it worked like charm.
0

Well in my case I had this exact same problem when accesing the API through Amazon API Gateway. Turned out I forgot to allow multipart ContentType on API Gateway. Kind of weird the requests still made it to my server and text files worked fine.

1 Comment

can u share how exactly u allowed multipart ContentType on API Gateway?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.