【问题标题】:Upload pdf in HTML and Deserialize json file以 HTML 格式上传 pdf 并反序列化 json 文件
【发布时间】:2016-09-21 19:52:13
【问题描述】:

我正在尝试以 html 格式上传文件,然后通过 restangular 将其发送到我的数据库。 我的前端是 angular 和 typescript 的组合,但上传是一个表单。

<form enctype="multipart/form-data">
    <fieldset class="form-group" ng-repeat="field in $ctrl.metadata.fields">
        <label ng-if="field.inputType !== 'hidden'" for="{{field.propertyKey}}"><strong>{{field.name}}</strong></label>
        <input ng-if="field.inputType !== 'select' && field.inputType !== 'file'" class="form-control" type="{{field.inputType}}" name="{{field.propertyKey}}" id="{{field.propertyKey}}" ng-model="$ctrl.data[field.propertyKey]"/>
        <input ng-if="field.inputType === 'file'" class="form-control" ngf-select type="{{field.inputType}}" name="{{field.propertyKey}}" id="{{field.propertyKey}}" ng-model="$ctrl.data[field.propertyKey]"/>
        <sp-dropdown ng-if="field.inputType === 'select'" value="$ctrl.data[field.propertyKey]" api-domain="field.linkedObjectApiDomain" linked-object-name="field.linkedObjectName"></sp-dropdown>
    </fieldset>
    <button class="btn btn-primary" ng-click="$ctrl.save({item: $ctrl.data})">Save</button>
    <button ng-if="$ctrl.metadata.buttons.hasOpen" class="btn btn-primary" ng-click="$ctrl.open()">Open</button>
</form>

我使用ng-file-upload 对文件进行了数据绑定。

保存后我们进入这个打字稿保存方法。

public save(item: any): any  {
    console.log("item to save is ", item);
    console.log("rapport is ", item["rapport"]);

    if (item.id === undefined) {
        this.restService.save(this.metadata.apiDomain, item).then((addedItem: any) => {
            toastr.success(`${addedItem.naam} successfully created.`, `Overzicht Dossiers Created`);
        });
    } else {
        this.restService.update(this.metadata.apiDomain, item).then((updatedItem: any) => {
            toastr.success(`${updatedItem.naam} successfully updated.`, `Overzicht Dossiers Updated`);
        });
    }
}

文件的第二个日志给出了json:

最后修改:1463402787393 最后修改日期:2016 年 5 月 16 日星期一 14:46:27 GMT+0200(浪漫 (zomertijd)) 名称:“报告.pdf” 尺寸:83605 类型:“应用程序/pdf” 上传:承诺 webkitRelativePath:"" __proto__:文件

在服务器端,我正在使用我自己没有设置的 spring 项目,但重要的文件是我的类,它应该存储这些数据 卷宗 /* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package be.ugent.lca.data.entities;

import be.ugent.sherpa.entity.BaseEntity;
import java.sql.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.Lob;
import javax.persistence.ManyToOne;
import javax.persistence.OneToOne;

/**
 *
 * @author Sam
 */
@Entity
//@JsonDeserialize(using = DossierDeserializer.class) 
//@JsonSerialize(using = DossierSerializer.class) 
public class Dossier extends BaseEntity{
    private String externDossierNr;
    private String internDossierNr;
    private Date datum;
    private Boolean doc;
    private Date refKlantDatum;
    private String refKlantVerwijzing;
    private String verantw;


    @OneToOne(fetch=FetchType.LAZY, mappedBy="dossier")
    private Offerte offerte;

    private String status;

    @ManyToOne(fetch=FetchType.EAGER)
    @JoinColumn(name = "persoon")
    private Persoon persoon;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "OrganisatieFirma")
    private OrganisatieFirma organisatieFirma;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "OrganisatieIntern")
    private OrganisatieIntern organisatieIntern;

    @Lob
    @Column(length=100000)
    private byte[] rapport;

    public Offerte getOfferte() {
        return offerte;
    }

    public void setOfferte(Offerte offerte) {
        this.offerte = offerte;
    }

    public byte[] getRapport() {
        return rapport;
    }

    public void setRapport(byte[] rapport) {
        this.rapport = rapport;
    }

    public OrganisatieFirma getOrganisatieFirma() {
        return organisatieFirma;
    }

    public String getExternDossierNr() {
        return externDossierNr;
    }

    public void setExternDossierNr(String externDossierNr) {
        this.externDossierNr = externDossierNr;
    }

    public String getInternDossierNr() {
        return internDossierNr;
    }

    public void setInternDossierNr(String internDossierNr) {
        this.internDossierNr = internDossierNr;
    }

    public void setOrganisatieFirma(OrganisatieFirma organisatieFirma) {
        this.organisatieFirma = organisatieFirma;
    }

    public OrganisatieIntern getOrganisatieIntern() {
        return organisatieIntern;
    }

    public void setOrganisatieIntern(OrganisatieIntern organisatieIntern) {
        this.organisatieIntern = organisatieIntern;
    }

    public Persoon getPersoon() {
        return persoon;
    }

    public void setPersoon(Persoon persoon) {
        this.persoon = persoon;
    }

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    public Date getDatum() {
        return datum;
    }

    public void setDatum(Date datum) {
        this.datum = datum;
    }

    public Date getRefKlantDatum() {
        return refKlantDatum;
    }

    public void setRefKlantDatum(Date refKlantDatum) {
        this.refKlantDatum = refKlantDatum;
    }

    public String getRefKlantVerwijzing() {
        return refKlantVerwijzing;
    }

    public void setRefKlantVerwijzing(String refKlantVerwijzing) {
        this.refKlantVerwijzing = refKlantVerwijzing;
    }

    public String getVerantw() {
        return verantw;
    }

    public void setVerantw(String verantw) {
        this.verantw = verantw;
    }

    public Boolean getDoc() {
        return doc;
    }

    public void setDoc(Boolean doc) {
        this.doc = doc;
    }

}

还有我的这个类的存储库

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package be.ugent.lca.data.repository;

import be.ugent.lca.data.entities.Dossier;
import be.ugent.lca.data.query.DossierQuery;
import be.ugent.sherpa.repository.RestRepository;
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
/**
 *
 * @author Sam
 */
@RepositoryRestResource(collectionResourceRel = "dossiers", path = "dossiers")
public interface DossierRepository extends RestRepository<Dossier, DossierQuery<?>>{

}

当试图将文件保存到我的数据库时,服务器给出了这个异常 原因:com.fasterxml.jackson.databind.JsonMappingException:无法从 START_OBJECT 令牌中反序列化 byte[] 的实例

这让我相信我必须为 Dossier 编写自己的反序列化程序 因此:

package be.ugent.lca.data.entities.deserializers;


import be.ugent.lca.data.entities.Dossier;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.ObjectCodec;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;
import java.io.IOException;

public class DossierDeserializer extends JsonDeserializer {
    @Override
    public Dossier deserialize(JsonParser jsonParser,
            DeserializationContext deserializationContext) throws IOException {
        ObjectCodec oc = jsonParser.getCodec();
        JsonNode root = oc.readTree(jsonParser);
        Dossier dossier = new Dossier();

        dossier.setExternDossierNr(root.get("externDossierNr").asText());
        dossier.setInternDossierNr(root.get("internDossierNr").asText());

        return dossier;
    }
}

但我的问题是我不知道如何准确地反序列化文件 json,因为写出 root.get("rapport") 会返回一个空字符串。

任何帮助将不胜感激。

【问题讨论】:

    标签: html angularjs json spring-data


    【解决方案1】:

    我已经解决了文件上传问题。

    首先,我将文件上传与我的其余数据分开,这样我就不必为所有有效的东西重写自动反序列化。

    this.restService.save(this.metadata.apiDomain, item).then((addedItem: any) => {
        toastr.success(`${addedItem.naam} successfully created.`, `Overzicht Dossiers Created`);
        console.log("created item ", addedItem);
        var fd = new FormData();
        fd.append("rapport", item["rapport"]);
    
        this.restService.one('dossiers/' + addedItem.id + '/rapport').withHttpConfig({transformRequest: angular.identity}).customPOST(fd, '', undefined, {'Content-Type': undefined}).then(
            (addedDossier: any) => {
                console.log("posted dossier ", addedDossier);
            }
        );
    });
    

    在我正常保存的回调中,我将自定义帖子发送到 dossiers/{id}/rapport 为此我需要一个自定义控制器。

    @BasePathAwareController
    @RequestMapping("/dossiers/{id}")
    @ExposesResourceFor(Dossier.class)
    public class DossierController {
    

    BasePathAwawareController 确保所有自动生成的、您没有覆盖的路径保持存在。

    @Autowired
    private DossierRepository dossierRepository;
    

    通过这个我注入我的存储库以连接到我的数据库。

    @RequestMapping(path = "/rapport", method = RequestMethod.POST)//,headers = "content-type=multipart/form-data") 
    public @ResponseBody String postRapport(@PathVariable("id") Long id,@RequestParam("rapport") MultipartFile file) {
        String name = "rapport";
        System.out.println("Entered custom file upload with id " + id);
        if (!file.isEmpty()) {
            try {
                byte[] bytes = file.getBytes();
                Dossier dossier = dossierRepository.findOne(id);
                dossier.setRapport(bytes);
    
                dossierRepository.save(dossier);
                return "You successfully uploaded " + name + " into " + name + "-uploaded !";
            } catch (Exception e) {
                return "You failed to upload " + name + " => " + e.getMessage();
            }
        } else {
            return "You failed to upload " + name + " because the file was empty.";
        }
    }
    

    这样我就可以成功上传文件了。

    【讨论】:

    • 我不确定我是否应该包括我的“Json 字符串”有什么问题,或者这是否会使我的答案不必要地复杂化。或者我应该在我的问题中编辑它,因为它不是解决方案的一部分?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-02
    • 1970-01-01
    • 1970-01-01
    • 2011-07-09
    • 2011-08-14
    • 2014-07-17
    相关资源
    最近更新 更多