FileUpload with JAX-RS

后端 未结 5 1099
忘了有多久
忘了有多久 2020-11-30 05:08

I try to do file upload from a JavaScript client to a JAX-RS Java server.

I use the following REST upload function on my server:

@POST
@Produces(\'ap         


        
相关标签:
5条回答
  • 2020-11-30 05:14

    On Server Side you can use something like this

    @POST
    @Path("/fileupload")  //Your Path or URL to call this service
    @Consumes(MediaType.MULTIPART_FORM_DATA)
    public Response uploadFile(
            @DefaultValue("true") @FormDataParam("enabled") boolean enabled,
            @FormDataParam("file") InputStream uploadedInputStream,
            @FormDataParam("file") FormDataContentDisposition fileDetail) {
         //Your local disk path where you want to store the file
        String uploadedFileLocation = "D://uploadedFiles/" + fileDetail.getFileName();
        System.out.println(uploadedFileLocation);
        // save it
        File  objFile=new File(uploadedFileLocation);
        if(objFile.exists())
        {
            objFile.delete();
    
        }
    
        saveToFile(uploadedInputStream, uploadedFileLocation);
    
        String output = "File uploaded via Jersey based RESTFul Webservice to: " + uploadedFileLocation;
    
        return Response.status(200).entity(output).build();
    
    }
    private void saveToFile(InputStream uploadedInputStream,
            String uploadedFileLocation) {
    
        try {
            OutputStream out = null;
            int read = 0;
            byte[] bytes = new byte[1024];
    
            out = new FileOutputStream(new File(uploadedFileLocation));
            while ((read = uploadedInputStream.read(bytes)) != -1) {
                out.write(bytes, 0, read);
            }
            out.flush();
            out.close();
        } catch (IOException e) {
    
            e.printStackTrace();
        }
    
    }
    

    Again this can be checked with the client code in java with

    public class TryFile {
    public static void main(String[] ar)
           throws HttpException, IOException, URISyntaxException {
        TryFile t = new TryFile();
        t.method();
    }
    public void method() throws HttpException, IOException, URISyntaxException {
        String url = "http://localhost:8080/...../fileupload";  //Your service URL
        String fileName = ""; //file name to be uploaded
        HttpClient httpclient = new DefaultHttpClient();
        HttpPost httppost = new HttpPost(url);
        FileBody fileContent = new FiSystem.out.println("hello");
        StringBody comment = new StringBody("Filename: " + fileName);
        MultipartEntity reqEntity = new MultipartEntity();
        reqEntity.addPart("file", fileContent);
        httppost.setEntity(reqEntity);
    
        HttpResponse response = httpclient.execute(httppost);
        HttpEntity resEntity = response.getEntity();
    }
    }
    

    With HTML, you can simply check with this code

    <html>
    <body>
    <h1>Upload File with RESTFul WebService</h1>
    <form action="<Your service URL (htp://localhost:8080/.../fileupload)" method="post" enctype="multipart/form-data">
       <p>
        Choose a file : <input type="file" name="file" />
       </p>
       <input type="submit" value="Upload" />
    </form>
    

    To get QueryParam, Check @QueryParam or for header param use @HeaderParam

    Example of @QueryParam

    Example of @HeaderParam

    Try this, hope this helps you with your problem.

    0 讨论(0)
  • 2020-11-30 05:18

    Here is what we did to upload file (images in our case) :
    Server side

    @POST
    @RolesAllowed("USER")
    @Path("/upload")
    @Consumes("multipart/form-data")
    public Response uploadFile(MultipartFormDataInput input) throws IOException
    {
        File local;
        final String UPLOADED_FILE_PATH = filesRoot; // Check applicationContext-Server.properties file
    
        //Get API input data
        Map<String, List<InputPart>> uploadForm = input.getFormDataMap();
    
        //The file name
        String fileName;
        String pathFileName = "";
    
    
        //Get file data to save
        List<InputPart> inputParts = uploadForm.get("attachment");
    
        try
        {
            for (InputPart inputPart : inputParts)
            {
                //Use this header for extra processing if required
                MultivaluedMap<String, String> header = inputPart.getHeaders();
                fileName = getFileName(header);
                String tmp = new SimpleDateFormat("yyyyMMddhhmmss").format(new Date());
                pathFileName = "images/upload/" + tmp + '_' + fileName + ".png";
                fileName = UPLOADED_FILE_PATH + pathFileName;
    
                // convert the uploaded file to input stream
                InputStream inputStream = inputPart.getBody(InputStream.class, null);
    
                byte[] bytes = IOUtils.toByteArray(inputStream);
                // constructs upload file path
    
                writeFile(bytes, fileName);
                // NOTE : The Target picture boundary is 800x600. Should be specified somewhere else ?
                BufferedImage scaledP = getScaledPicture(fileName, 800, 600, RenderingHints.VALUE_INTERPOLATION_BILINEAR, false);
                ByteArrayOutputStream os = new ByteArrayOutputStream();
                ImageIO.write(scaledP, "png", os);
                local = new File(fileName);
                ImageIO.write(scaledP, "png", local);
            }
        }
        catch (Exception e)
        {
            e.printStackTrace();
            return Response.serverError().build();
        }
        return Response.status(201).entity(pathFileName).build();
    
    }
    

    For the client side, we use AngularJS which is coded by another team. I won't be able to explain about it, but here is the code :

        $scope.setPicture = function (element)
    {
      var t = new Date();
      console.log(t + ' - ' + t.getMilliseconds());
    
      // Only process image files.
      if (!element[0].type.match('image.*'))
      {
        console.log('File is not an image');
        Error.current.element = $document[0].getElementById('comet-project-upload');
        Error.current.message = 'Please select a picture.';
        $scope.$apply();
      }
      else if (element[0].size > 10 * 1024 * 1024)
      {
        console.log('File is too big');
        Error.current.element = $document[0].getElementById('comet-project-upload');
        Error.current.message = 'File is too big. Please select another file.';
        $scope.$apply();
      }
      else
      {
        self.animSpinner = true;
    
        var fd = new FormData();
        //Take the first file
        fd.append('attachment', element[0]);
        //Note : attachment is the compulsory name ?
    
        Project.uploadImage(fd).then(
          function (data)
          {
            self.animSpinner = false;
    
            // self.$apply not needed because $digest already in progress
            self.projectPicture = data;
          },
          function ()
          {
            self.animSpinner = false;
            Error.current.element = $document[0].getElementById('comet-project-upload');
            Error.current.message = 'Error with the server when uploading the image';
    
            console.error('Picture Upload failed! ' + status + ' ' + headers + ' ' + config);
          }
        );
      }
    };
    

    And the uploadImage function :

        this.uploadImage = function (imageData)
    {
      var deferred = $q.defer();
    
      $http.post('/comet/api/image/upload', imageData,
        {
          headers: { 'Content-Type': undefined, Authorization: User.hash },
          //This method will allow us to change how the data is sent up to the server
          // for which we'll need to encapsulate the model data in 'FormData'
          transformRequest: angular.identity
          //The cool part is the undefined content-type and the transformRequest: angular.identity
          // that give at the $http the ability to choose the right "content-type" and manage
          // the boundary needed when handling multipart data.
        })
        .success(function (data/*, status, headers, config*/)
        {
          deferred.resolve(data);
        })
        .error(function (data, status, headers, config)
        {
          console.error('Picture Upload failed! ' + status + ' ' + headers + ' ' + config);
          deferred.reject();
        });
    
      return deferred.promise;
    };
    

    Hope it will help you ...

    0 讨论(0)
  • 2020-11-30 05:22

    Add enctype="multipart/form-data" in your form submitter code and @Consumes(MediaType.MULTIPART_FORM_DATA_TYPE) on your @POST method so that we know we are submitting a multipart file and the rest api can consume it. Your rest api method could look like

    @POST
    @Path("/uploadfile")
    @Consumes(MediaType.MULTIPART_FORM_DATA)
    public Response upload(
        @FormDataParam("file") InputStream fileInputStream, 
        @FormDataParam("file") FormDataContentDisposition disposition) {
            //...
    }
    

    or

     @POST
     @Path("/uploadfile")
     public void post(File file) {
        Reader reader = new Reader(new FileInputStream(file));
        // ... 
     }
    

    This will create a temporary file on server. It reads from the network and saves into the temporary file.

    To program defensively, I would check the content type metadata of the file being uploaded.

    0 讨论(0)
  • 2020-11-30 05:24

    With pure JAX-RS, assuming you don't need a filename, upload method looks like:

        @POST
        @Consumes(MediaType.MULTIPART_FORM_DATA)
        public void upload(InputStream file, @QueryParam("foo") String foo) {
            // Read file contents from the InputStream and do whatever you need
        }
    
    0 讨论(0)
  • 2020-11-30 05:38

    There is no Jax-RS way to do this. Each server have their own extensions, all using Multi-part form submissions. For example, in CXF, the following will allow you to upload via a multipart form. (Attachment is a CXF specific extension)

    @Consumes(MediaType.MULTIPART_FORM_DATA)
    public Response uploadFile(@Multipart(value = "vendor") String vendor,
            @Multipart(value = "uploadedFile") Attachment attr) {
    

    whereas the following is the same for Jersey (FormDataParam is a Jersey extension):

     @Consumes(MediaType.MULTIPART_FORM_DATA_TYPE)
     public String postForm(
             @DefaultValue("true") @FormDataParam("enabled") boolean enabled,
             @FormDataParam("data") FileData bean,
             @FormDataParam("file") InputStream file,
             @FormDataParam("file") FormDataContentDisposition fileDisposition) {
    

    (I've ignored the @Path, @POST and @Produces, and other non-relevant annotations.)

    0 讨论(0)
提交回复
热议问题