Jersey Restful 웹 서비스에서 다른 객체와 함께 파일 업로드
직원 데이터와 함께 이미지를 업로드하여 시스템에 직원 정보를 만들고 싶습니다. 저지를 사용하여 다른 휴식 전화로 할 수 있습니다. 그러나 나는 한 번의 휴식으로 성취하고 싶다. 나는 구조 아래에 제공합니다. 이 점에서 어떻게해야하는지 도와주세요.
@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
}
시도 할 때마다 Chrome 우편 배달부에 오류가 발생합니다. 내 Employee json의 간단한 구조는 다음과 같습니다.
{
"Name": "John",
"Age": 23,
"Email": "john@gmail.com",
"Adrs": {
"DoorNo": "12-A",
"Street": "Street-11",
"City": "Bangalore",
"Country": "Karnataka"
}
}
하지만 두 번의 다른 호출을해서 할 수는 있지만 한 번의 휴식 호출로 달성하여 직원의 실제 데이터와 파일을받을 수 있도록하고 싶습니다.
이와 관련하여 도움을 요청하십시오.
두 개의 Content-Type
s를 가질 수 없습니다 (기술적으로는 아래에서 수행하는 작업이지만 멀티 파트의 각 부분으로 분리되어 있지만 주요 유형은 멀티 파트입니다). 그것은 기본적으로 당신이 당신의 방법으로 기대하는 것입니다. 기본 미디어 유형으로 mutlipart 와 json을 함께 기대하고 있습니다. Employee
데이터는 여러 부분의 일부가 될 필요가있다. 그래서 당신은 추가 할 수 있습니다 @FormDataParam("emp")
을 위해 Employee
.
@FormDataParam("emp") Employee emp) { ...
테스트에 사용한 클래스는 다음과 같습니다.
@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();
}
}
먼저 클라이언트 API로 테스트하여 작동하는지 확인했습니다.
@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
= "{"
+ " \"id\": 1234,"
+ " \"name\": \"Peeskillet\""
+ "}";
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();
}
방금 테스트를 위해 and 필드가 있는 간단한 Employee
클래스를 만들었습니다 . 이것은 완벽하게 잘 작동합니다. 이미지를 표시하고 콘텐츠 배치를 인쇄하고 개체를 인쇄 합니다.id
name
Employee
나는 Postman에 너무 익숙하지 않아서 마지막으로 테스트를 저장했습니다 :-)
응답을 볼 수 있듯이 잘 작동하는 것 같습니다 "Cool Tools"
. 그러나 인쇄 된 Employee
데이터를 살펴보면 null이라는 것을 알 수 있습니다. 클라이언트 API로 제대로 작동했기 때문에 이상합니다.
미리보기 창을 보면 문제가 있음을 알 수 있습니다.
본문 부분 에는 Content-Type
헤더 가 없습니다 emp
. 클라이언트 API에서 내가 명시 적으로 설정 한 것을 볼 수 있습니다.
MultiPart multipartEntity = new FormDataMultiPart()
.field("emp", empPartJson, MediaType.APPLICATION_JSON_TYPE)
.bodyPart(filePart);
그래서 나는 이것이 실제로 완전한 대답의 일부일 뿐이라고 생각합니다 . 말씀 드렸듯이 저는 Postman에 익숙하지 않아서 Content-Type
개별 신체 부위에 s 를 설정하는 방법을 모릅니다 . image/png
이미지에 대한 자동 이미지 부분 (나는 그것이 단지 파일 확장자에 의해 결정되었다 추측)을 위해 나를 위해 설정되었다. 이것을 알아낼 수 있다면 문제가 해결되어야합니다. 이 작업을 수행하는 방법을 찾으면 답변으로 게시하십시오.
그리고 완전성을 위해 ...
기본 구성 :
의존:
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-multipart</artifactId>
<version>${jersey2.version}</version>
</dependency>
클라이언트 구성 :
final Client client = ClientBuilder.newBuilder()
.register(MultiPartFeature.class)
.build();
서버 구성 :
// Create JAX-RS application.
final Application application = new ResourceConfig()
.packages("org.glassfish.jersey.examples.multipart")
.register(MultiPartFeature.class);
최신 정보
따라서 Postman 클라이언트에서 볼 수 있듯이 일부 클라이언트는 FormData
(js)를 사용할 때의 기본 기능과 관련하여 브라우저를 포함하여 개별 부분의 Content-Type을 설정할 수 없습니다 .
클라이언트가이 문제를 해결하기를 기대할 수 없으므로 데이터를 수신 할 때 역 직렬화하기 전에 명시 적으로 Content-Type을 설정해야합니다. 예를 들면
@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를 얻는 것은 약간의 추가 작업이지만 클라이언트가 자신의 솔루션을 찾으려고 강요하는 것보다 더 나은 솔루션입니다.
Asides
- 이 주석 에는 기본 HttpUrlConnection이 아닌 다른 커넥터를 사용하는 경우 관심이있을 수 있는 대화 가 있습니다.
아래 코드를 이용하여 MULTIPART FORM DATA를 이용하여 Form에서 Image File 및 Data에 접근 할 수 있습니다.
@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) {}
}
}
}
ApplicationConfig는 파일 업로드를 활성화하기 위해 glassfish.jersey.media ..에서 MultiPartFeature.class를 등록해야합니다.
@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);
}
나는 peeskillet에 대한 의견을 추가하고 싶지만 평판 포인트가 50이 아니므로 답변으로 추가합니다.
Jersey 클라이언트 2.21.1에서 @peeskillet 솔루션을 시도했을 때 400 오류가 발생했습니다. 클라이언트 코드에 다음을 추가하면 작동했습니다.
MediaType contentType = MediaType.MULTIPART_FORM_DATA_TYPE;
contentType = Boundary.addBoundary(contentType);
Response response = t.request().post(
Entity.entity(multipartEntity, contentType));
요청 후 호출에서 하드 코딩 된 MediaType.MULTIPART_FORM_DATA 대신.
파일 업로드 예제를 사용했습니다.
http://www.mkyong.com/webservices/jax-rs/file-upload-example-in-jersey/
내 리소스 클래스에는 아래 방법이 있습니다.
@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);
}
내 attachService.java에는 아래 방법이 있습니다.
public void saveAttachment(String flename, byte[] is) {
// TODO Auto-generated method stub
attachmentDao.saveAttachment(flename,is);
}
Dao에서 나는 가지고있다
attach.setData(is);
attach.setFileName(flename);
내 HBM 매핑에서
<property name="data" type="binary" >
<column name="data" />
</property>
이것은 .PDF, .TXT, .PNG 등과 같은 모든 유형의 파일에서 작동합니다.
'Nice programing' 카테고리의 다른 글
목록 멤버 노출을위한 IEnumerable vs IReadonlyCollection vs ReadonlyCollection (0) | 2021.01.07 |
---|---|
304를 반환하는 요청을 방지하는 방법 (0) | 2021.01.07 |
docker-compose yml 파일 유효성 검사 (0) | 2021.01.07 |
RabbiMQ "Ready" "Unacked"메시지 유형이란? (0) | 2021.01.07 |
a [a [0]] = 1은 정의되지 않은 동작을 생성합니까? (0) | 2021.01.07 |