2013-09-03 6 views
2

Я изучаю создание веб-сервисов с Java на данный момент. Если быть точным, RESTful Webservices с JAX-RS и его исполнением Jersey. Я работаю над динамическим веб-проектом в Eclipse.Создайте новый веб-ресурс с помощью Джерси

Веб-служба должна позволять пользователю загружать файл со своего компьютера (он работает), а затем сохраняется на сервере (также работает). После того, как загрузка/сохранение службы должна вернуть URI, который указывает файл, и может использоваться для совместного использования файла с другими пользователями в Интернете (это не работает).

Возможно ли это с каркасом Джерси?

Я попытался провести некоторое исследование по этой теме, но поскольку я довольно новичок в этой теме, кажется, что я ищу неправильные ключевые слова.

Так вот что я придумал:

import java.io.File; 
import java.io.FileNotFoundException; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.OutputStream; 
import java.net.URI; 

import javax.servlet.ServletContext; 
import javax.ws.rs.Consumes; 
import javax.ws.rs.GET; 
import javax.ws.rs.POST; 
import javax.ws.rs.Path; 
import javax.ws.rs.PathParam; 
import javax.ws.rs.Produces; 
import javax.ws.rs.client.Entity; 
import javax.ws.rs.core.Context; 
import javax.ws.rs.core.MediaType; 
import javax.ws.rs.core.Response; 
import javax.ws.rs.core.UriInfo; 

import com.sun.jersey.core.header.FormDataContentDisposition; 
import com.sun.jersey.multipart.FormDataParam; 


@Path("/file") 
public class Upload { 

@Context 
private UriInfo uriInfo; 
@Context 
private ServletContext context; 

@GET 
@Path("/upload") 
@Produces(MediaType.TEXT_HTML) 
public String getUploadForm() { 

    StringBuilder htmlPageBuilder = new StringBuilder(); 

    htmlPageBuilder.append("<html>"); 
    htmlPageBuilder.append("<body>"); 
    htmlPageBuilder.append("<h1>File upload</h1>"); 
    htmlPageBuilder.append("<form action=\"rest/file/processed\" method=\"post\" enctype=\"multipart/form-data\">"); 
    htmlPageBuilder.append("<p>"); 
    htmlPageBuilder.append("Select a file : <input type=\"file\" name=\"file\" size=\"45\" />"); 
    htmlPageBuilder.append("</p>"); 
    htmlPageBuilder.append("<input type=\"submit\" value=\"Upload file\" />"); 
    htmlPageBuilder.append("</form>"); 
    htmlPageBuilder.append("</body>"); 
    htmlPageBuilder.append("</html>");  

    return htmlPageBuilder.toString();  
} 

@POST 
@Path("/rest/file/processed") 
@Consumes(MediaType.MULTIPART_FORM_DATA) 
public Response uploadFile(@FormDataParam("file") InputStream uploadInputStream, 
          @FormDataParam("file") FormDataContentDisposition fileDetail) { 

    String uploadedFilePath = "C:\\Tomcat\\Data\\"; 
    uploadedFilePath += fileDetail.getFileName(); 

    //write the file onto the server 
    File uploadedFile = this.writeToFile(uploadInputStream, uploadedFilePath); 
    String uploadedFileName = uploadedFile.getName(); 

    String output = "File uploaded to: " + uploadedFilePath + uploadedFileName; 

    URI location = uriInfo.getAbsolutePathBuilder().path(uploadedFileName).build(); 

    //return Response.ok(output).build(); 
    return Response.created(location).entity(Entity.text(output)).build(); 
} 

private File writeToFile(InputStream uploadInputStream, String uploadedFilePath) { 

    File uploadedFile = new File(uploadedFilePath); 

    try { 

     OutputStream out = new FileOutputStream(uploadedFile); 

     int read = 0; 

     byte[] bytes = new byte[1024]; 

     while((read = uploadInputStream.read(bytes)) != -1) { 

      out.write(bytes, 0, read); 
     } 

     out.flush(); 
     out.close(); 
    } 
    catch (FileNotFoundException e) { 

     e.printStackTrace(); 
    } 
    catch (IOException e) { 

     } 
    } 
} 

Таким образом, для метода POST возврата отклика на OK. Другой ответ как URI даже не появляется (часть, которую я прокомментировал). Я думаю, причина в том, что ресурс не существует.

Я очень ценю любую помощь.

Редактировать

Я попробовал решение, предоставляемое Aradom и включал в себя genson библиотеку. Теперь я получаю новый NullPointerException. Вот трассировки стека:

Severe: Servlet.service() for servlet [RestServlet] in context with path [/FirstRestWebService] threw exception 
java.lang.NullPointerException 
    at com.owlike.genson.reflect.BeanViewDescriptorProvider$BeanViewPropertyFactory.createAccessor(BeanViewDescriptorProvider.java:122) 
    at com.owlike.genson.reflect.BeanPropertyFactory$CompositeFactory.createAccessor(BeanPropertyFactory.java:49) 
    at com.owlike.genson.reflect.BaseBeanDescriptorProvider.provideMethodAccessors(BaseBeanDescriptorProvider.java:187) 
    at com.owlike.genson.reflect.BaseBeanDescriptorProvider.provideBeanPropertyAccessors(BaseBeanDescriptorProvider.java:94) 
    at com.owlike.genson.reflect.AbstractBeanDescriptorProvider.provide(AbstractBeanDescriptorProvider.java:106) 
    at com.owlike.genson.convert.BasicConvertersFactory.provide(BasicConvertersFactory.java:109) 
    at com.owlike.genson.convert.BasicConvertersFactory.create(BasicConvertersFactory.java:74) 
    at com.owlike.genson.convert.BasicConvertersFactory.create(BasicConvertersFactory.java:56) 
    at com.owlike.genson.reflect.AbstractBeanDescriptorProvider$ContextualFactoryDecorator.create(AbstractBeanDescriptorProvider.java:79) 
    at com.owlike.genson.reflect.AbstractBeanDescriptorProvider$ContextualFactoryDecorator.create(AbstractBeanDescriptorProvider.java:68) 
    at com.owlike.genson.convert.ChainedFactory.create(ChainedFactory.java:93) 
    at com.owlike.genson.convert.ChainedFactory.create(ChainedFactory.java:80) 
    at com.owlike.genson.convert.ChainedFactory.create(ChainedFactory.java:93) 
    at com.owlike.genson.convert.ChainedFactory.create(ChainedFactory.java:80) 
    at com.owlike.genson.convert.ChainedFactory.create(ChainedFactory.java:93) 
    at com.owlike.genson.convert.ChainedFactory.create(ChainedFactory.java:80) 
    at com.owlike.genson.convert.CircularClassReferenceConverterFactory.create(CircularClassReferenceConverterFactory.java:58) 
    at com.owlike.genson.convert.CircularClassReferenceConverterFactory.create(CircularClassReferenceConverterFactory.java:22) 
    at com.owlike.genson.Genson.provideConverter(Genson.java:196) 
    at com.owlike.genson.Genson.serialize(Genson.java:340) 
    at com.owlike.genson.ext.jaxrs.GensonJsonConverter.writeTo(GensonJsonConverter.java:91) 
    at com.sun.jersey.spi.container.ContainerResponse.write(ContainerResponse.java:306) 
    at com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:1479) 
    at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1391) 
    at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1381) 
    at com.sun.jersey.spi.container.servlet.WebComponent.service(WebComponent.java:416) 
    at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:538) 
    at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:716) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:728) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) 
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222) 
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123) 
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472) 
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171) 
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99) 
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953) 
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118) 
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408) 
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1023) 
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589) 
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) 
    at java.lang.Thread.run(Unknown Source) 

Я пытаюсь заглянуть в библиотеку genson, чтобы увидеть, если я найду что-то об этом исключением. Я очень ценю помощь до сих пор.

+0

Вы можете поделиться загруженным файлом в своей локальной сети? – mike

+0

какая версия genson вы используете? попробуйте версию 0.98 – eugen

ответ

0

Продолжая ваш код. Просто сделайте это небольшое изменение на вашем методе POST

URI location = ... 
String output = ... 
return Response.created(location).entity(Entity.text(output)).build(); 
+0

Привет, спасибо за ваш быстрый ответ. Теперь я получаю исключение. Вот трассировка стека: javax.ws.rs.WebApplicationException: com.sun.jersey.api.MessageException: писатель тела сообщения для Java-класса javax.ws.rs.client.Entity и класс типа Java javax.ws.rs .client.Entity и MIME-тип/октет-поток не были найдены – Scyla

+0

Попробуйте добавить библиотеку Genson в свой путь к классам http://code.google.com/p/genson/. Это json <> java streaming и databinding api. Он хорошо интегрируется с трикотажем, чтобы заставить вас работать, вам нужна конфигурация 0. Джерси обнаруживает, что библиотека находится в вашем пути к классам и позволяет отображать json, делегируя Genson. – Andromeda

+0

Я добавил библиотеку, но получил новое исключение. Обновлен мой вопрос, поэтому он включает в себя трассировку стека. – Scyla

0

Привет извините за поздний ответ, но потребовалось некоторое время, пока я не вернулся в этот проект. Теперь, когда я немного более опытен, я знаю, что ответ Андромедаса правильный.

Однако я попытаюсь дать более подробное объяснение, как я смог решить проблему. Это может быть полезно для тех, у кого такая же проблема.

Занимать свой собственный код:

//get the context of the servlet 
@Context 
private ServletContext servletContext; 
@Context 
private UriInfo uriInfo; 

@POST 
@Path("/rest/file/processed") 
@Consumes(MediaType.MULTIPART_FORM_DATA) 
public Response uploadFile(@FormDataParam("file") InputStream uploadInputStream, 
          @FormDataParam("file") FormDataContentDisposition fileDetail) { 


    //create a new folder structure in the webapp folder 
    //webapp 
    // | 
    // -> temp 
    //  | 
    //  -> tempFiles 
    //get the path of the tempFiles folder 
    String uploadedFilePath = servletContext.getRealPath("/temp/tempFiles/"); 
    //add the file name to the path 
    uploadedFilePath += fileDetail.getFileName(); 

    //write the file onto the server 
    File uploadedFile = this.writeToFile(uploadInputStream, uploadedFilePath); 

    URI fileUri = null; 

    try { 

     fileUri = new URI(uriInfo.getBaseUri().toString() + "temp/tempFiles/" + uploadedFile.getName()); 
     //if you have any additional url-patterns in your web.xml file you might have to remove them i.e. 
     //fileUri = new URI(uriInfo.getBaseUri().toString().replace("/url-pattern", "") + "temp/tempFiles/" + uploadedFile.getName()); 
    } 
    catch (URISyntaxException e) { 

     uploadedFile.delete(); 

     //create a fitting response 
     return Response.status(404).entity("Could not create the URI: " + fileUri).build(); 
    } 

    //create a fitting response 
    return Response.status(201).entity("Successfully uploaded the file. \n Resource created at: <a href=" + fileUri + ">" + fileUri + "</a>").build(); 
} 

Имейте в виду, что этот файл будет временно сохранен только в каталоге сервера. Если вы хотите сохранить постоянное хранилище, вы можете сохранить его в другом каталоге или отправить его на файловый сервер через FTP (что-то я пытаюсь выяснить прямо сейчас).

Я не знаю, является ли это лучшим решением, но оно работает для меня до сих пор.

Приветствия.

Смежные вопросы