현재 프로젝트에서 프론트 - react , 백엔드 - gin(golang) + (elasticSearch , hyperledger fabric) 를 통해 개발하고 있다.
프로젝트에서 블록체인 플랫폼에 체인코드를 업로드 , 다운로드 , 설치 기능을 개발해야 한다.
다른 프로젝트에서도 해당 내용을 사용하게 될 것 같아 기록해 두려고 한다.
react->gin 파일 업로드
기존 방식을 스마트 컨트랙트 생성 시 직접 사용자가 json을 지정해서 넣어야한다. 이로 인해 json에 대한 정보를 알 지 못하는 사용자는 사용할 수 없으며 서버에서 원하는 형식에 맞지 않으면 오류가 발생하였다.
이를 해결하기 위해 drag n drop 방식으로 파일(체인코드) 자체를 업로드 할 수 있도록 수정하였다.
let formData = new FormData();
formData.append('file',file.rawFile)
formData.append('data',JSON.stringify(params.data))
var ans = httpClient(`${apiUrl}/${resource}/file`, {
method: 'POST',
body:formData,
}).then(({json}) => ({
data: {...params.data, id: String(json.id)},
}))
기존 사용하던 Article data를 활용해야 하나, file을 보내기 위해서는 기존 형식이 아닌 form data 형식으로 보내야 하기 때문에 formdata에 기존 json data를 string으로 변환하여 넣어주었다. ( 복잡한 json 형태는 form data에 넣을 수 없음)
type Article struct {
ID string `json:"id"`
Name string `json:"name"`
Author string `json:"author"`
UploadDate string `json:"uploaded"`
Description string `json:"description"`
Platform string `json:"platform"`
SignaturePolicy string `json:"signature_policy"`
CCLanguages []*CCLanguage `json:"cc_languages"`
AppLanguages []map[string]string `json:"app_languages"`
Versions []map[string]string `json:"versions"`
}
// FileUpload
// @Summary If clients send cc package file, then upload zip file at /Downloads/chaincodes and install system channel.
// @Produce json
// @Tags dashboard
// @Success 200 "successful operation"
// @Router /fabric/dashboard/smart-contracts/file [post]
func FileUpload(c *gin.Context) {
// get zip file and upload it
rawData := c.PostForm("data")
var inputData search.Article
json.Unmarshal([]byte(rawData), &inputData)
file, _ := c.FormFile("file")
// 스마트 컨트랙트 이름에 맞춰 압축파일 저장
c.SaveUploadedFile(file, fmt.Sprintf(`/home/jeho/Downloads/chaincodes/%s.tar.gz`, inputData.Name))
log.Println("zip file uploaded successfully")
// save smart constarct info
inputData.UploadDate = fmt.Sprintf(time.Now().UTC().Format("2006-01-02"))
log.Println(inputData.UploadDate)
res, err := search.AddDocumentToES(&inputData)
if err != nil {
c.IndentedJSON(http.StatusInternalServerError, gin.H{"message": err})
return
}
c.IndentedJSON(http.StatusOK, gin.H{"message": res})
}
data를 받고 elasticsearch에 추가해준다. file과 data를 받아온다. 단, json data를 string 형식으로 받아오기 때문에 Unmarshal을 통해 파싱해준다. 현재는 로컬 폴더에 저장하지만 블록체인 플랫폼 자체를 클라우드에 올리면 그 때 s3같은 곳으로 옮겨야 할 것 같다.
gin-> react 파일 다운로드
기존 cors 에러로 인해 cors-anywhere.herokuapp.com에서 정적인 데이터만 다운로드 하는 것을 수정하였다.
const downloadSC = (e : any) => {
const name = e.target.getAttribute('name')
console.log("Downloading Smart Contract.")
fetch(`http://localhost:8080/fabric/dashboard/downloadCC?name=${name}`,{method: 'GET'})
.then(response => response.blob())
.then(blob => {
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `${name}.tar.gz`;
document.body.appendChild(a);
a.click();
setTimeout((_ : any) => {
window.URL.revokeObjectURL(url);
}, 60000);
a.remove();
})
.catch(error => console.log('error', error));
};
기존 http 방식과 달리 blob 형태로 data를 받는다. Hyperledger Fabric 에서 제공하는 체인코드 패키징 방식을 사용하기 위해서 tar.gz형식으로 다운로드 받도록 하였다.
func DownloadCC(c *gin.Context) {
fileName := c.Query("name")
log.Println(fileName)
targetPath := filepath.Join(CCPATHROOT, fmt.Sprintf("%s.tar.gz", fileName))
log.Println(targetPath)
//파일이 없을 때
if !strings.HasPrefix(filepath.Clean(targetPath), CCPATHROOT) {
c.String(403, "It doesn't exist")
return
}
//크롬에서 File로 인식하고 다운로드 받기 위한 header 설정
c.Header("Content-Description", "File Transfer")
c.Header("Content-Transfer-Encoding", "binary")
c.Header("Content-Disposition", "attachment; filename="+fileName)
c.Header("Content-Type", "application/octet-stream")
c.File(targetPath)
}
프론트에서 요청한 file을 보내기 위해 query 인자의 이름을 갖는 파일을 찾아서 보내도록 하였다. 또한, Hyperledger Fabric에서 tar.gz 파일로 패키징하며, 이를 이용하여 바로 채널에 설치할 수 있기 때문에 tar.gz파일으로 고정하였다.
File을 보내야 하기 때문에 content-transfer-encoding에 binary로 전달되도록 하였으며, 또한 content-type 에 application/octet-stream을 명시해 주었다.
'블록체인' 카테고리의 다른 글
블록체인 해커톤 후기 (0) | 2022.12.02 |
---|---|
FireFly와 Fabric의 스마트 컨트랙트 배포,실행 비교 (0) | 2022.09.04 |
Hyperledger Fabric SDK를 활용한 트랜잭션 수행 (0) | 2022.09.04 |
하이퍼 레저 패브릭 - 개요 (0) | 2022.06.29 |