Хранение изображения с помощью ajax-запроса в приложении Postgresql в Spring - PullRequest
0 голосов
/ 12 июня 2018

Я пытаюсь сохранить изображение в postgresql db из моего приложения Spring, но я застрял с множеством проблем и путаницы.

Сначала позвольте мне дать вам обзор кода моего приложения Spring:

var documentData = new FormData();
    function update(){
        var fname=document.getElementById("fname").value;
        var lname=document.getElementById("lname").value;
        var password=document.getElementById("password").value.trim();
        var email=document.getElementById("email").value;

        documentData.append('fname',fname);
        documentData.append('lname',lname);
        documentData.append('password',password);
        documentData.append('email',email);
        documentData.append('profilePic',$('#profilePic').attr('src'));
        alert($('#profilePic').attr('src'));            
            $
            .ajax({
                type : 'PUT',
                url : baseUrl + "/restApi/UpdateUser",
                data : JSON
                        .stringify({
                             documentData
                        }),
                        success: function(){
                            location.reload(true);          
                           },

                error : function(e) {

                },
                dataType : "json",
                contentType : "application/json"
            });

        }

    }
    $(function () {
    $(":file").change(function () {
        if (this.files && this.files[0]) {
            var reader = new FileReader();
            reader.onload = imageIsLoaded;
            reader.readAsDataURL(this.files[0]);

        }
    });

});

function imageIsLoaded(e) {
    $('#profilePic').attr('src', e.target.result);
    $('#viewPic').attr('src',e.target.result);
};

У меня есть этот контроллер

@RequestMapping(value = "/restApi/UpdateUser", method = RequestMethod.PUT, headers = "Accept=application/json")
    public ServiceResponse modifyUser(@RequestBody Object user)
    {
        return setDataPut("http://localhost:7020/UpdateUser",user,getUserObject().getUsername(),getUserObject().getPassword());
    }

В моем методе setDataPut я отправляю ответ с GSON

WebResource webResource = client
               .resource(path);
            ClientResponse response = webResource.type("application/json").accept("application/json")
               .put(ClientResponse.class, gson.toJson(object));

В модельном классе я взял переменную типа byte [] , а в db я сделал столбец с типом bytea .

@CrossOrigin
    @RequestMapping(value = "/ModifyUser", method = RequestMethod.PUT, headers = "Accept=application/json")
    public ServiceResponse modifyUser(@RequestBody User user) {
 /*Code which deals with storing User data*/

}

Итак, я взял все данные через модель User class.Раньше все работало отлично, пока я не захотел сохранить изображение.Ничего не сохраняется, нет ошибок.

Путаница: Если я отправляю изображение с некоторыми данными, я должен изменить тип содержимого или добавить enctype как «multipart / form-data».Но если я использую multipart, то что следует изменить в заголовках.Как @produces @consumes.Главное сомнение в том, нужно ли мне преобразовывать изображение в двоичный код перед отправкой?

Проблема: У меня проблемы с сохранением изображения в postgresql через ajax-запрос.Пожалуйста, посмотрите мой код в чем проблема.

1 Ответ

0 голосов
/ 14 июня 2018

Вы задаете довольно много вопросов по одному вопросу здесь.По сути, вы спрашиваете, как загрузить файлы из браузера / клиента на сервер на базе Spring, как обработать эту загрузку на сервере на основе Spring, чтобы сохранить ее в базе данных Postgresql и связать ее с моей сущностью User, чтобыЯ могу получить это снова позже.

Итак, давайте ответим на все это для вас.

Давайте начнем со стороны клиента.Этот код загрузит выбранный файл в существующий ресурс: -

index.html

<html>
  <head>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.js"></script>
    <script>
      function upload() {
        var data = new FormData();
        data.append('file', jQuery('#file')[0].files[0]);

        jQuery.ajax({
            url: '/userImage/userId',
            data: data,
            cache: false,
            contentType: false,
            processData: false,
            method: 'POST',
            type: 'POST', // For jQuery < 1.9
            success: function(data){
                alert(data);
            }
        });
      }
    </script>
  </head>
  <body>
    <div>
        <h1>New File</h1>
        <input type="file" id="file" name="file"/>
        <button onclick="upload()">Upload</button>
    </div>
  </body>
</html>

Теперь обратим наше внимание на серверную часть Spring-bsed.Чтобы абстрагироваться от реализации того, как именно сохранить загруженный файл в базе данных (и как обновить его, как извлечь его, как удалить и т. Д.), Я бы использовал Spring Content в противном случаеу вас есть много кода для написания того, что Spring Content уже реализует для вас.

Итак, добавьте следующие зависимости:

pom.xml

    <dependency>
        <groupId>com.github.paulcwarren</groupId>
        <artifactId>spring-content-jpa</artifactId>
        <version>0.1.0</version>   // 0.0.11 for Spring Boot 1 dependencies
    </dependency>

Сконфигурируйте создание схемы базы данных в одном из ваших классов конфигурации:

Config.java

@Configuration
@EnableJpaStores // enable JPA-based storage
public class PostgresqlTestConfig {

    ...dataSource and entityManager, etc beans...    

    @Value("/org/springframework/content/jpa/schema-drop-postgresql.sql")
    private Resource dropReopsitoryTables;

    @Value("/org/springframework/content/jpa/schema-postgresql.sql")
    private Resource dataReopsitorySchema;

    @Bean
    DataSourceInitializer datasourceInitializer() {
        ResourceDatabasePopulator databasePopulator =
                new ResourceDatabasePopulator();

        databasePopulator.addScript(dropReopsitoryTables);
        databasePopulator.addScript(dataReopsitorySchema);
        databasePopulator.setIgnoreFailedDrops(true);

        DataSourceInitializer initializer = new DataSourceInitializer();
        initializer.setDataSource(dataSource());
        initializer.setDatabasePopulator(databasePopulator);

        return initializer;
    }
}

Свяжите контент с вашей сущностью User:

User.java

@Entity
public class User {

    ...existing fields...

    @ContentId private String contentId;
    private String mimeType;
}

Создайте хранилище UserStore:

UserImageStore.java

public interface UserImageStore extends AssociativeStore<User, String> {
}

Обновите свойконтроллер для обработки загрузки файлов, сохранения их в базе данных и связывания этого сохраненного изображения с вашей сущностью:

UserController.java

    @Autowired
    private UserImageStore store;

    ...

    @RequestMapping(value="/userImage/{userId}", method = RequestMethod.POST)
    public ResponseEntity<?> setContent(@PathVariable("userId") Long id, @RequestParam("file") MultipartFile file) 
            throws IOException {

        User user = // fetch your existing user here
        user.setMimeType(file.getContentType());

        String originalFilename = file.getOriginalFilename();
        InputStream is = file.getInputStream();
        OutputStream os = ((WritableResource)store.getResource(originalFilename)).getOutputStream();

        IOUtils.copyLarge(is, os);

        IOUtils.closeQuietly(is);
        IOUtils.closeQuietly(os);

        // associate content (this will update the @ContentId field)
        store.associate(user, originalFilename);

        // save updated content-related info
        save(user); 

        return new ResponseEntity<Object>(HttpStatus.OK);
    }
    return null;

    @RequestMapping(value="/userImage/{userId}", method = RequestMethod.GET)
    public ResponseEntity<?> getContent(@PathVariable("userId") Long id) {

        User user = // fetch your existing user here
        Resource r = store.getResource(user.getContentId());
        HttpHeaders headers = new HttpHeaders();
        headers.setContentLength(r.getContentLength());
        headers.set("Content-Type", user.getMimeType());
        return new ResponseEntity<Object>(r, headers, HttpStatus.OK);
    }
    return null;
}

Вот и все.Поэтому здесь произойдет следующее: когда ваше приложение запускается, оно видит зависимость от spring-content-jpa, а затем видит ваше UserImageStore.Предполагается, что вы хотите хранить изображения (BLOB) в jpa, и внедряет реализацию JPA интерфейса UserImageStore, что означает, что вам не нужно писать его самостоятельно.Spring Content скрывает реализацию, но предоставляет относительно простой интерфейс (фактически основанный на Spring Resource), который составляет @Autowired в вашем контроллере, делая эту реализацию простой.

В любом случае, дайте мне знать, если вы используете Spring Data или Spring Boot, и я могу обновить этот ответ, чтобы он был более актуальным для вас.

HTH

...