Soru Jersey'deki diğer web siteleriyle birlikte dosya yükleme


Çalışan verileri ile birlikte bir görüntü yükleyerek sistemde çalışan bilgileri oluşturmak istiyorum. Bunu jersey kullanarak farklı dinlenme çağrıları ile yapabilirim. Ama ben bir dinlenme çağrısında ulaşmak istiyorum. Yapının altında sağlarım. Lütfen bana bu konuda nasıl yardımcı olunur.

@POST
@Path("/upload2")
@Consumes({MediaType.MULTIPART_FORM_DATA,MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public Response uploadFileWithData(
        @FormDataParam("file") InputStream fileInputStream,
        @FormDataParam("file") FormDataContentDisposition contentDispositionHeader,
        Employee emp) {

//..... business login

}

Ne zaman yapmaya çalışıyorum, Chrome postacıda hata alıyorum. Çalışan jsonumun basit yapısı aşağıda verilmiştir.

{
    "Name": "John",
    "Age": 23,
    "Email": "john@gmail.com",
    "Adrs": {
        "DoorNo": "12-A",
        "Street": "Street-11",
        "City": "Bangalore",
        "Country": "Karnataka"
    }
}

Ancak bunu iki farklı çağrı yaparak yapabilirim, ancak bir dinlenme çağrısında başarılı olmak istiyorum, böylece dosyayı ve asıl verileri çalışanın alabiliyorum.

Bu konuda yardımcı olmanızı rica ediyorum.


39
2017-12-22 19:59


Menşei




Cevaplar:


İki tane olamaz Content-Types (teknik olarak aşağıda yapmakta olduğumuz şey budur, ancak bunlar multipartın her bölümü ile ayrılır, ancak ana tip multiparttır). Bu, sizin yönteminizle beklediğiniz şeydir. Mutlipart bekliyorsunuz ve json birlikte ana medya türü olarak. Employee Verilerin çok parçalı bir parçası olması gerekiyor. Böylece ekleyebilirsiniz @FormDataParam("emp") için Employee.

@FormDataParam("emp") Employee emp) { ...

İşte test için kullandığım sınıf

@Path("/multipart")
public class MultipartResource {

    @POST
    @Path("/upload2")
    @Consumes({MediaType.MULTIPART_FORM_DATA})
    public Response uploadFileWithData(
            @FormDataParam("file") InputStream fileInputStream,
            @FormDataParam("file") FormDataContentDisposition cdh,
            @FormDataParam("emp") Employee emp) throws Exception{

        Image img = ImageIO.read(fileInputStream);
        JOptionPane.showMessageDialog(null, new JLabel(new ImageIcon(img)));
        System.out.println(cdh.getName());
        System.out.println(emp);

        return Response.ok("Cool Tools!").build();
    } 
}

İlk önce, çalıştığından emin olmak için istemci API'siyle test ettim

@Test
public void testGetIt() throws Exception {

    final Client client = ClientBuilder.newBuilder()
        .register(MultiPartFeature.class)
        .build();
    WebTarget t = client.target(Main.BASE_URI).path("multipart").path("upload2");

    FileDataBodyPart filePart = new FileDataBodyPart("file", 
                                             new File("stackoverflow.png"));
    // UPDATE: just tested again, and the below code is not needed.
    // It's redundant. Using the FileDataBodyPart already sets the
    // Content-Disposition information
    filePart.setContentDisposition(
            FormDataContentDisposition.name("file")
                                    .fileName("stackoverflow.png").build());

    String empPartJson
            = "{\n"
            + "    \"id\": 1234,\n"
            + "    \"name\": \"Peeskillet\"\n"
            + "}\n"
            + "";

    MultiPart multipartEntity = new FormDataMultiPart()
            .field("emp", empPartJson, MediaType.APPLICATION_JSON_TYPE)
            .bodyPart(filePart);

    Response response = t.request().post(
            Entity.entity(multipartEntity, multipartEntity.getMediaType()));
    System.out.println(response.getStatus());
    System.out.println(response.readEntity(String.class));

    response.close();
}

Yeni bir basit yarattım Employee bir sınıf id ve name test için alan. Bu mükemmel çalışıyor. Resmi gösterir, içerik düzenini yazdırır ve yazdırır. Employee nesne.

Postman'a fazla aşina değilim, bu yüzden bu testi son :-) için sakladım.

enter image description here

Yanıtı görebileceğiniz gibi iyi çalışıyor gibi görünüyor "Cool Tools". Ama eğer basılmışa bakarsak Employee veri, boş olduğunu göreceğiz. Bu garip çünkü istemci API ile iyi çalıştı.

Önizleme penceresine bakarsak, sorunu göreceğiz

enter image description here

Orada hiçbir Content-Type için başlık emp vücut parçası. İstemci API'sinde açıkça görüyorum.

MultiPart multipartEntity = new FormDataMultiPart()
        .field("emp", empPartJson, MediaType.APPLICATION_JSON_TYPE)
        .bodyPart(filePart);

Yani sanırım bu gerçekten sadece Bölüm tam bir cevap. Dediğim gibi, Postman'a aşina değilim. Yani nasıl ayarlanacağımı bilmiyorum Content-TypeBireysel vücut parçaları için. image/png görüntü için görüntü kısmı için açıkça benim için ayarlandı. Bunu anlayabilirseniz, sorun çözülmelidir. Lütfen, bunun nasıl yapılacağını öğrenirseniz, cevap olarak gönderin.


Ve sadece bütünlük için ...

Temel yapılandırmaları:

Bağımlılık:

<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-multipart</artifactId>
    <version>${jersey2.version}</version>
</dependency>

İstemci yapılandırması:

final Client client = ClientBuilder.newBuilder()
    .register(MultiPartFeature.class)
    .build();

Sunucu yapılandırması:

// Create JAX-RS application.
final Application application = new ResourceConfig()
    .packages("org.glassfish.jersey.examples.multipart")
    .register(MultiPartFeature.class);

GÜNCELLEŞTİRME

Postman istemcisinden de görebileceğiniz gibi, bazı istemciler tek tek parçaların İçerik Türü'nü ayarlayamazlar; bu, tarayıcıyı, kullanıldıklarında varsayılan özelliklerine göre içerir. FormData (Js).

Müşterinin bu konuyla ilgili bir şeyler bulmasını bekleyemeyiz, bu yüzden yapabileceğimiz, verileri alırken, içerik türünü seri hale getirmeden önce açıkça belirler. Örneğin

@POST
@Path("upload2")
@Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadFileAndJSON(@FormDataParam("emp") FormDataBodyPart jsonPart,
                                  @FormDataParam("file") FormDataBodyPart bodyPart) { 
     jsonPart.setMediaType(MediaType.APPLICATION_JSON_TYPE);
     Employee emp = jsonPart.getValueAs(Employee.class);
}

POJO'yu almak için biraz fazladan iş var, ama müşterinin kendi çözümünü bulmaya çalışmasını zorlamaktan daha iyi bir çözüm.


72
2017-12-23 05:09



Merhaba, istemci API'sındaki kodu güncellemek için sizi (veya bunu okuyan ve bilen herhangi bir başka tür) sorun olabilir. Örneğin, ilk satırda "c.target" var ama burada c nedir? - AbuMariam
@ user3223841 En alttaki "İstemci Yapılandırması" na bakın. c == client. Ve kodu güncelledim. Teşekkür ederim. - Paul Samsotha
Kodunuzu büyük dosyalarda test ettiniz mi? alırım aynı form gönderiminde hata - gkiko
Yapabilseydim sana 100 tane hediye verirdim. Bu, iyi araştırılmış, güncel, yararlı, geçici çözümler ile cevaplanmış olması gerektiği anlamına gelir! - cen
Dosya bölümü için @AzamatAlmukhametov, FormDataBodyPart kullanarak gerekli değildi. Sanırım sadece kopyalayıp yapıştırıyordum. Onu bir şey olarak bırakabilirsin InputStream parametre. JSON bölümü için sadece FormDataBodyPart'a ihtiyaç vardır çünkü medya türünü değiştirmemiz gerekiyor. Ancak dosya için ham girdi akışını alabiliriz. Başka bir yol kullanmaktır bodyPart.getValueAs(InputStream.class)ama buna gerek yok. Sadece parametreyi InputStream - Paul Samsotha


Görüntü Dosyasına ve verilere MULTIPART FORM DATA kullanarak bir formdan erişebilirsiniz. Aşağıdaki kodu kullanarak.

@POST
@Path("/UpdateProfile")
@Consumes(value={MediaType.APPLICATION_JSON,MediaType.MULTIPART_FORM_DATA})
@Produces(value={MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})
public Response updateProfile(
    @FormDataParam("file") InputStream fileInputStream,
    @FormDataParam("file") FormDataContentDisposition contentDispositionHeader,
    @FormDataParam("ProfileInfo") String ProfileInfo,
    @FormDataParam("registrationId") String registrationId) {

    String filePath= "/filepath/"+contentDispositionHeader.getFileName();

    OutputStream outputStream = null;
    try {
        int read = 0;
        byte[] bytes = new byte[1024];
        outputStream = new FileOutputStream(new File(filePath));

        while ((read = fileInputStream.read(bytes)) != -1) {
            outputStream.write(bytes, 0, read);
        }

        outputStream.flush();
        outputStream.close();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if (outputStream != null) { 
            try {
                outputStream.close();
            } catch(Exception ex) {}
        }
    }
}

1
2017-10-18 14:08





ApplicationConfig uygulamanız dosya yüklemeyi etkinleştirmek için MultiPartFeature.class'ı glassfish.jersey.media dosyasından kaydetmelidir.

@javax.ws.rs.ApplicationPath(ResourcePath.API_ROOT)
public class ApplicationConfig extends ResourceConfig {  
public ApplicationConfig() {
        //register the necessary headers files needed from client
        register(CORSConfigurationFilter.class);
        //The jackson feature and provider is used for object serialization
        //between client and server objects in to a json
        register(JacksonFeature.class);
        register(JacksonProvider.class);
        //Glassfish multipart file uploader feature
        register(MultiPartFeature.class);
        //inject and registered all resources class using the package
        //not to be tempered with
        packages("com.flexisaf.safhrms.client.resources");
        register(RESTRequestFilter.class);
    }

0
2018-01-04 18:08





Dosya yükleme örneği kullandım,

http://www.mkyong.com/webservices/jax-rs/file-upload-example-in-jersey/

kaynak sınıfımda aşağıdaki yönteme sahibim

@POST
    @Path("/upload")
    @Consumes(MediaType.MULTIPART_FORM_DATA)
    public Response  attachupload(@FormDataParam("file") byte[] is,
@FormDataParam("file") FormDataContentDisposition fileDetail,
@FormDataParam("fileName") String flename){
attachService.saveAttachment(flename,is);
}

benim attachService.java içinde aşağıdaki yönteme sahibim

 public void saveAttachment(String flename,  byte[] is) {
            // TODO Auto-generated method stub
         attachmentDao.saveAttachment(flename,is);

        }

Dao'da var

attach.setData(is);
attach.setFileName(flename);

HBM haritalamada olduğu gibi

<property name="data" type="binary" >
            <column name="data" />
</property>

Bu, .PDF, .TXT, .PNG vb. Gibi tüm dosyalar için çalışıyor.


0
2017-07-20 06:37



SADECE BENİM YAŞAMIYLA YANITLAYIN ... [1] Ben bir bira borcumu ödüyorum. - Mário Carvalho


Peeskillet'e bir yorum eklemek istiyorum ama 50 itibar puanına sahip olmamak, dolayısıyla yanıt olarak eklemek istiyorum:

Jersey istemcisi 2.21.1 ile @peeskillet çözümünü denediğimde 400 hata oluştu. Müşteri koduma eklediğimde çalıştı:

  MediaType contentType = MediaType.MULTIPART_FORM_DATA_TYPE;
  contentType = Boundary.addBoundary(contentType);

  Response response = t.request().post(
        Entity.entity(multipartEntity, contentType));

istek sonrası aramada kodlanmış MediaType.MULTIPART_FORM_DATA yerine.


0
2018-02-03 09:25



Sınırı manuel olarak oluşturmanız gerekmez. Sadece kullanabilirsiniz multipartEntity.getMediaType(). Aslında kullanıyordum MediaType.MULTIPART_FORM_DATA sınırı eklemeyen Ama sen getMediaType() yöntem MutliPart, o irade sınırı var. - Paul Samsotha


İstemci tarafında "Content-Type: multipart / form-data" öğesini ayarlayın ve işi yapmalısınız.


-4
2018-03-13 19:52