How to consume image upload data as byte[] using Spring MVC 3

12,908

Solution 1

First, if you're form is uploading an image, make sure your content type is "multipart/form-data". You might want to change your RequestMapping as follows:

@RequestMapping(value = "uploadImage", method = RequestMethod.POST, headers={"content-type=multipart/form-data"})

Also, I'd suggest using CommonsMultipartFile to handle the upload. Change your function signature as follows, where "fieldName" is the name of the input field in your form:

public void uploadImage(byte[] uploadData, Writer writer, HttpServletRequest request, @RequestParam("fieldName") CommonsMultipartFile file)

Then you can get the raw bytes as follows:

file.getBytes()

Make sure you include the commons-fileupload dependency for CommonsMultipartFile.

I'm using spring3 + jquery ajaxform and this works like a charm. Hope this helps!

Solution 2

Following is the JavaScript and HTML code I used on the client side that got things working:

JavaScript:

function createUploader(){           
    var uploader = new qq.FileUploader({
    element: document.getElementById('file-uploader'),
    action: 'uploadImage',
    allowedExtensions: ['jpg', 'jpeg', 'png', 'gif'],
    debug: true,
    onSubmit: function(id, fileName){
        console.log("id - " + id + ", fileName - " + fileName);
    },
        onComplete: function(id, fileName, responseJSON) {
            console.log("responseJSON -  " + responseJSON);
        }
    });           
}
window.onload = createUploader; 

HTML:

<div id="file-uploader" >
    <noscript>
    <p>Please enable JavaScript to upload your property location images</p>
    </noscript>
</div>

Controller:

@Controller
public class FranchiseeLocationImageController {

    private static final Log logger = LogFactory.getLog(FranchiseeLocationImageController.class);

    @Autowired
    private ServletContext servletContext;

    @Autowired
    private FranchiseeLocationImageService franchiseeLocationImageService;  

    @RequestMapping(value = "uploadImage", method = RequestMethod.POST)
    public void uploadImage(byte[] qqfile, Writer writer, @RequestParam("qqfile") String img, HttpServletRequest request, HttpServletResponse response) throws IOException, JSONException{
        FranchiseeLocationImage image = null;       
        PrintWriter pr = null;
        InputStream is =  null;
        File file = null;
        FileOutputStream fos = null;
        String filename = request.getHeader("X-File-Name");
        String imageId = FilenameUtils.removeExtension(img);
        String imageFormat = franchiseeLocationImageService.getImageFormat();
        String outputDir = servletContext.getRealPath("") + File.separator + franchiseeLocationImageService.getImagesDirectory() + File.separator;
        File baseDirectory = null;
        File output = null;
        String path = FilenameUtils.removeExtension(img) + "." + imageFormat;
        File outputDirectory = null;
        HttpSession session = request.getSession();
        /*
        HttpSession session = request.getSession(false);
        if(session == null) {
            session = request.getSession();
        }
        */
        List<String> franchiseeLocationImages = (List<String>) session.getAttribute("franchiseeLocationImages");
        if(franchiseeLocationImages == null) {
            franchiseeLocationImages = new ArrayList<String>();
        }

        logger.debug( "filename - " + filename + " | img - " + img + " | img name - " + FilenameUtils.removeExtension(img) + " | img format - " + FilenameUtils.getExtension(img) + " | uploadData - " + qqfile + " | imageFormat - " + imageFormat);   
        /**
         * Reading the image being uploaded and writing it to images/franchiseeLocation folder ["qqfile" is used instead of "X-File-Name" as "X-File-Name" gives encoded HTML name with "%20" for " "]
         */
        try {
            pr = response.getWriter();
            is =  request.getInputStream();

            /*
            baseDirectory = new File(outputDir);
            baseDirectory.mkdirs();
            file = new File(outputDir, FilenameUtils.removeExtension(img) + "." + imageFormat);         
            fos = new FileOutputStream(file);
            int copiedNum = IOUtils.copy(is, fos);
            */

            outputDirectory = new File(outputDir);
            outputDirectory.mkdirs();
            output = new File(outputDirectory, path);
            BufferedImage sourceImage = ImageIO.read(is);
            boolean written = ImageIO.write(sourceImage, imageFormat, output);
            franchiseeLocationImages.add(img);
            session.setAttribute("franchiseeLocationImages", franchiseeLocationImages);

            logger.debug("franchiseeLocationImages - " + franchiseeLocationImages);
            logger.debug("outputDirectory - " + outputDirectory + " | output - " + output +  " | sourceImage - " + sourceImage + " | is - " + is + " | file - " + file + " |fos - " + fos + " | copiedNum - " + "copiedNum" + " | baseDirectory - " + baseDirectory + " | sourceImage - " + sourceImage + " | written - " + written);
            /*
            image = franchiseeLocationImageService.processProductImage(qqfile, imageId);
            JSONObject json = new JSONObject();
            json.put("path", image.getPath());
            json.put("id", image.getId());
            writer.write(json.toString());
            */
            pr.print("{success: true}");
        } finally {
            writer.close();
            /*
            try {
                fos.close();
                is.close();
            } catch (IOException ignored) {
            }
            */
            pr.flush();
            pr.close();
        }
    }

    @InitBinder
    protected void initBinder(ServletRequestDataBinder binder) {
        binder.registerCustomEditor(byte[].class,
                new ByteArrayMultipartFileEditor());
    }

    private static String html2text(String html) {
        return Jsoup.parse(html).text();
    }


}
Share:
12,908
skip
Author by

skip

Updated on June 04, 2022

Comments

  • skip
    skip almost 2 years

    I need write the image data in a particular directory on the server side but I am getting a null for the raw byte[] image upload data that I am trying to send from an html form and jquery ajaxuploader plugin from here.

    Following is the snippet from the controller I am using to handle raw bytes of image being uploaded:

    @RequestMapping(value = "uploadImage", method = RequestMethod.POST)
    public void uploadImage(byte[] uploadData, Writer writer, HttpServletRequest request) throws IOException, JSONException {
        //uploadData is turning out to be null
        //..
    }
    
    @InitBinder
    protected void initBinder(ServletRequestDataBinder binder) {
        binder.registerCustomEditor(byte[].class,
                new ByteArrayMultipartFileEditor());
    }
    

    I have got the following configured in the spring configuration file for handling uploads:

    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    </bean>
    

    I am using Spring MVC 3. Could someone guide me on how to send raw bytes of upload data?

    Thanks.