Zenodo: APIλ₯Ό 톡해 μƒŒλ“œλ°•μŠ€μ— λŒ€μš©λŸ‰ 파일 μ—…λ‘œλ“œ μ‹€νŒ¨

에 λ§Œλ“  2016λ…„ 09μ›” 26일  Β·  6μ½”λ©˜νŠΈ  Β·  좜처: zenodo/zenodo

μ•ˆλ…•ν•˜μ„Έμš”,

λ‹€μŒ μ½”λ“œλ₯Ό μ‚¬μš©ν•˜μ—¬ Python μš”μ²­ 및 Zenodo API(μƒŒλ“œλ°•μŠ€)λ₯Ό 톡해 > 100MB의 ν…ŒμŠ€νŠΈ νŒŒμΌμ„ μ—…λ‘œλ“œν•˜λ €κ³  ν•  λ•Œ

data = {'filename': 'test.zip'}
files = {'file': open(filename, 'rb')}
r = requests.post("https://sandbox.zenodo.org/api/deposit/depositions/%s/files?access_token=TOKEN" % deposition_id, data=data, files=files)

http 였λ₯˜ μ½”λ“œ 413 ("413 Request Entity Too Large", btwλŠ” zenodo API λ¬Έμ„œμ— λ¬Έμ„œν™”λ˜μ§€ μ•ŠμŒ)λ₯Ό λ°˜ν™˜ν•©λ‹ˆλ‹€.

< 100MB 파일둜 ν…ŒμŠ€νŠΈν•œ λ™μΌν•œ μ½”λ“œκ°€ μž‘λ™ν•˜κ³  201 λ°˜ν™˜ν•©λ‹ˆλ‹€.

파일 크기 μ œν•œμ— λ„λ‹¬ν–ˆμŠ΅λ‹ˆκΉŒ? (λ§Œμ•½ κ·Έλ ‡λ‹€λ©΄ 이것을 λ¬Έμ„œμ— μΆ”κ°€ν•˜λŠ” 것이 쒋을 κ²ƒμž…λ‹ˆλ‹€). μ•„λ‹ˆλ©΄ "μš”μ²­" νŒ¨ν‚€μ§€ λ•Œλ¬ΈμΌ μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€. 데이터λ₯Ό μ—¬λŸ¬ λΆ€λΆ„μœΌλ‘œ λ„£μ–΄μ•Ό ν•©λ‹ˆκΉŒ?

Enhancement

κ°€μž₯ μœ μš©ν•œ λŒ“κΈ€

λˆ„κ΅°κ°€ 이 문제λ₯Ό μ ‘ν•  경우λ₯Ό λŒ€λΉ„ν•˜μ—¬ μƒˆ APIλ₯Ό μ‚¬μš©ν•˜μ—¬ 파일 μ—…λ‘œλ“œ 뢀뢄을 μˆ˜ν–‰ν•˜λŠ” Python이 μžˆμŠ΅λ‹ˆλ‹€. μ΄λŠ” 단일 νŒŒμΌμ„ μ—…λ‘œλ“œν•˜κΈ° μœ„ν•΄ μœ„μ—μ„œ μ„€λͺ…ν•œ CURL 호좜과 λ™μΌν•©λ‹ˆλ‹€. λ¬Έμ„œν™” 된 API둜 μ‹€νŒ¨ν•œ 160MB 파일둜 ν…ŒμŠ€νŠΈν–ˆμŠ΅λ‹ˆλ‹€. 이것은 λ˜ν•œ μš”μ²­(λ¬Έμ„œν™”λœ APIκ°€ μ‚¬μš©ν•˜λŠ”)을 μ‚¬μš©ν•˜κ³  λ‹¨μˆœνžˆ μƒˆ μ œμΆœμ„ λ§Œλ“€κ³  νŒŒμΌμ„ μ—…λ‘œλ“œν•©λ‹ˆλ‹€. μ‚¬μš©λœ URL은 μƒŒλ“œλ°•μŠ€ URLμž…λ‹ˆλ‹€.

import requests

r = requests.post('https://sandbox.zenodo.org/api/deposit/depositions',
                        params={'access_token': ACCESS_TOKEN}, json={},
                        headers={"Content-Type": "application/json"})

print r.status_code

bucket_url = r.json()['links']['bucket']

filename='bigfile.txt'
r = requests.put('%s/%s' % (bucket_url,filename),
                data=open(filename, 'rb'),
                headers={"Accept":"application/json",
                "Authorization":"Bearer %s" % ACCESS_TOKEN,
                "Content-Type":"application/octet-stream"})

print r.status_code

λͺ¨λ“  6 λŒ“κΈ€

100MB보닀 큰 νŒŒμΌμ„ μ—…λ‘œλ“œν•˜λ €λ©΄ μƒˆλ‘œμš΄ 파일 μ—…λ‘œλ“œ API(아직 κ²Œμ‹œν•˜μ§€ μ•ŠμŒ)λ₯Ό μ‚¬μš©ν•΄μ•Ό ν•©λ‹ˆλ‹€. μ΄λŠ” ν˜„μž¬ APIκ°€ application/mulitpart-formdata λ₯Ό μ‚¬μš©ν•˜μ—¬ νŒŒμΌμ„ μ—…λ‘œλ“œν•˜λŠ” 데 그닀지 νš¨μœ¨μ μ΄μ§€ μ•ŠκΈ° λ•Œλ¬Έμž…λ‹ˆλ‹€. μƒˆ APIμ—μ„œλŠ” 훨씬 더 λΉ λ₯΄κ³  μ–‘μͺ½ λμ—μ„œ 인코딩/디코딩이 ν•„μš”ν•˜μ§€ μ•Šμ€ PUT μš”μ²­μœΌλ‘œ 파일의 이진 μ½˜ν…μΈ λ₯Ό μŠ€νŠΈλ¦¬λ°ν•©λ‹ˆλ‹€. μ˜€λŠ˜μ€ 쑰금 이따 예제λ₯Ό λ³΄λ‚΄λ“œλ¦¬κ² μŠ΅λ‹ˆλ‹€.

쑰사해 μ£Όμ…”μ„œ κ°μ‚¬ν•©λ‹ˆλ‹€! λ‚˜λŠ” μƒˆλ‘œμš΄ API의 μ˜ˆμ— λŒ€ν•΄ ν₯λΆ„ν•©λ‹ˆλ‹€.
닀쀑 파트 양식 데이터 개체λ₯Ό μŠ€νŠΈλ¦¬λ°ν•  μˆ˜λ„ μžˆλŠ” python νŒ¨ν‚€μ§€ "requests-toolbelt"λ₯Ό κ³ λ €ν•˜κ³  싢을 μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€. κ·ΈλŸ¬λ‚˜ 인코딩 μš”κ΅¬ 사항이 μ—†λŠ” μ†”λ£¨μ…˜μ€ 높이 평가될 κ²ƒμž…λ‹ˆλ‹€.

이에 λŒ€ν•œ 닡변이 였래 μ§€μ—°λœ 점 μ‚¬κ³Όλ“œλ¦½λ‹ˆλ‹€.

1) 버킷 URL μ°ΎκΈ°:

$ curl -H "Accept: application/json" -H "Authorization: Bearer <access token>" "https://www.zenodo.org/api/deposit/depositions/<deposit id>"
{
  "links": {
    "bucket": "https://www.zenodo.org/api/files/<bucket id>",
    ...
  },
...

2) 버킷에 파일 μ—…λ‘œλ“œ

$ curl -X PUT -H "Accept: application/json" -H "Content-Type: application/octet-stream" -H "Authorization: Bearer <access_token>" -d @<path to local file> https://www.zenodo.org/api/files/<bucket id>/<filename>

λ²„ν‚·μ—λŠ” 버전이 μ§€μ •λ˜μ–΄ μžˆμœΌλ―€λ‘œ νŒŒμΌμ„ λ‹€μ‹œ μ™„μ „νžˆ μ œκ±°ν•˜λ €λ©΄ 버전 링크λ₯Ό μ‚¬μš©ν•΄μ•Ό ν•©λ‹ˆλ‹€. 버킷 λͺ©λ‘μ—μ„œ μ°ΎμœΌμ‹­μ‹œμ˜€.

$ curl -H "Accept: application/json" -H "Authorization: Bearer <access token>" "https://www.zenodo.org/api/files/<bucket id>”
{
  "contents": [
    {
      "links": {
        "version": "https://zenodo.org/api/files/<bucket id>/<filename>?versionId=<versionId>", 
        ...
      }, 
      "key": "<filename>", 
      ...
    }, 
   ...

파일 μ‚­μ œ:

$ curl -X DELETE -H "Accept: application/json" -H "Authorization: Bearer <access_token>" https://www.zenodo.org/api/files/<bucket id>/<filename>?versionId=<versionId>”

λˆ„κ΅°κ°€ 이 문제λ₯Ό μ ‘ν•  경우λ₯Ό λŒ€λΉ„ν•˜μ—¬ μƒˆ APIλ₯Ό μ‚¬μš©ν•˜μ—¬ 파일 μ—…λ‘œλ“œ 뢀뢄을 μˆ˜ν–‰ν•˜λŠ” Python이 μžˆμŠ΅λ‹ˆλ‹€. μ΄λŠ” 단일 νŒŒμΌμ„ μ—…λ‘œλ“œν•˜κΈ° μœ„ν•΄ μœ„μ—μ„œ μ„€λͺ…ν•œ CURL 호좜과 λ™μΌν•©λ‹ˆλ‹€. λ¬Έμ„œν™” 된 API둜 μ‹€νŒ¨ν•œ 160MB 파일둜 ν…ŒμŠ€νŠΈν–ˆμŠ΅λ‹ˆλ‹€. 이것은 λ˜ν•œ μš”μ²­(λ¬Έμ„œν™”λœ APIκ°€ μ‚¬μš©ν•˜λŠ”)을 μ‚¬μš©ν•˜κ³  λ‹¨μˆœνžˆ μƒˆ μ œμΆœμ„ λ§Œλ“€κ³  νŒŒμΌμ„ μ—…λ‘œλ“œν•©λ‹ˆλ‹€. μ‚¬μš©λœ URL은 μƒŒλ“œλ°•μŠ€ URLμž…λ‹ˆλ‹€.

import requests

r = requests.post('https://sandbox.zenodo.org/api/deposit/depositions',
                        params={'access_token': ACCESS_TOKEN}, json={},
                        headers={"Content-Type": "application/json"})

print r.status_code

bucket_url = r.json()['links']['bucket']

filename='bigfile.txt'
r = requests.put('%s/%s' % (bucket_url,filename),
                data=open(filename, 'rb'),
                headers={"Accept":"application/json",
                "Authorization":"Bearer %s" % ACCESS_TOKEN,
                "Content-Type":"application/octet-stream"})

print r.status_code

@lnielsen @jakelever
requests.put μ‚¬μš©ν•˜μ—¬ 청크 νŒŒμΌμ„ λ²„ν‚·μœΌλ‘œ μŠ€νŠΈλ¦¬λ°ν•  수 μžˆλ‹€κ³  μƒκ°ν•˜μ‹­λ‹ˆκΉŒ?
λ¬Έλ§₯:
λ©”λͺ¨λ¦¬λ‚˜ λ””μŠ€ν¬μ— 미리 μ••μΆ• νŒŒμΌμ„ μƒμ„±ν•˜μ§€ μ•Šκ³  압좕을 ν’€κ³  싢은 λŒ€μš©λŸ‰ 파일 μ„ΈνŠΈκ°€ μžˆμŠ΅λ‹ˆλ‹€. μš”μ²­ λ©”μ„œλ“œμ˜ μ˜₯ν…Ÿ μŠ€νŠΈλ¦Όμ— 생성기 개체λ₯Ό μ „λ‹¬ν•˜κ³  μ‹ΆμŠ΅λ‹ˆλ‹€.

APIλ₯Ό μ‚¬μš©ν•˜μ—¬ νŒŒμΌμ„ μ—…λ‘œλ“œν•˜λŠ” λ™μ•ˆ 이것을 λ°œκ²¬ν–ˆμŠ΅λ‹ˆλ‹€. λ‚˜μ—κ²Œ 슀트리밍 APIλŠ” 986Kb 파일의 μ•½ 절반만 μ—…λ‘œλ“œλ˜μ–΄ PDFκ°€ μ†μƒλ˜μ—ˆκΈ° λ•Œλ¬Έμ— μ‹€νŒ¨ν–ˆμŠ΅λ‹ˆλ‹€. http://killtheradio.net/tricks-hacks/curl-cli-not-sending-full-file-data-when-using-data-binary/ 기반으둜 -d @<path to file> λ₯Ό -T <path to file> 둜 λŒ€μ²΄ -d @<path to file> curl λͺ…령쀄에 -T <path to file> 및 전체 파일이 μ—…λ‘œλ“œλ˜μ—ˆμŠ΅λ‹ˆλ‹€.

이 νŽ˜μ΄μ§€κ°€ 도움이 λ˜μ—ˆλ‚˜μš”?
0 / 5 - 0 λ“±κΈ‰